Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/whatsnew/fragments/10847.false_negative
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix ``used-before-assignment`` false negative when a variable has a bare type
annotation (without a value) and is only assigned inside ``except`` blocks.

Closes #10847
13 changes: 13 additions & 0 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,19 @@ def get_next_to_consume(self, node: nodes.Name) -> list[nodes.NodeNG] | None:
uncertain_nodes_set = set(uncertain_nodes)
found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]

# Filter out bare type annotations (AnnAssign without a value) when there
# are uncertain definitions. A bare annotation like `x: int` does not actually
# assign a value, so it should not suppress possibly-used-before-assignment
# when the real assignments are uncertain (e.g., in except blocks).
if found_nodes and self.consumed_uncertain.get(name):
found_nodes = [
n
for n in found_nodes
if not (
isinstance(n.parent, nodes.AnnAssign) and n.parent.value is None
)
]

return found_nodes

def _inferred_to_define_name_raise_or_return(
Expand Down
28 changes: 28 additions & 0 deletions tests/functional/u/used/used_before_assignment_type_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,31 @@ def loop_conditional_annotated_assignment():
data={"cat": "harf"}
token: str = data.get("cat") # [possibly-used-before-assignment]
print(token)


def bare_annotation_with_except_assignment():
"""A bare type annotation should not suppress used-before-assignment
when the only real assignments are in except blocks.

https://github.com/pylint-dev/pylint/issues/10847
"""
result = None
err: int # pylint: disable=unused-variable
try:
result = 1
except Exception: # pylint: disable=broad-exception-caught
Comment thread
jacobtylerwalls marked this conversation as resolved.
Outdated
err = 1
if not result:
print(err) # [used-before-assignment]


def bare_annotation_with_value_and_except():
"""A type annotation with a value should suppress the warning."""
result = None
err: int = 0
try:
result = 1
except Exception: # pylint: disable=broad-exception-caught
err = 1
if not result:
print(err)
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ used-before-assignment:28:10:28:18:value_assignment_after_access:Using variable
undefined-variable:62:14:62:17:decorator_returning_incorrect_function.wrapper_with_type_and_no_value:Undefined variable 'var':HIGH
possibly-used-before-assignment:97:17:97:21:conditional_annotated_assignment:Possibly using variable 'data' before assignment:CONTROL_FLOW
possibly-used-before-assignment:108:17:108:21:loop_conditional_annotated_assignment:Possibly using variable 'data' before assignment:CONTROL_FLOW
used-before-assignment:125:14:125:17:bare_annotation_with_except_assignment:Using variable 'err' before assignment:CONTROL_FLOW