Skip to content

F821: Declared only variables #21494

@eltoder

Description

@eltoder

Summary

Local variable annotations make annotated variables local even if there is no direct assignment. This is useful to create a local variable without an initial value. Ruff appears to not understand this usage. For example:

from typing import Callable

def make_cell() -> tuple[Callable[[], int], Callable[[int], None]]:
    x: int

    def getter() -> int:
        return x

    def setter(xx: int) -> None:
        nonlocal x
        x = xx

    return getter, setter

getter, setter = make_cell()
setter(123)
print(getter())

(playground link: https://play.ruff.rs/3bd90cac-2c87-48b0-9cb4-64fe2a53bf72)

This runs fine and passes mypy, however ruff produces a F821:

$ ruff check --isolated t.py
F821 Undefined name `x`
 --> t.py:7:16
  |
6 |     def getter() -> int:
7 |         return x
  |                ^
8 |
9 |     def setter(xx: int) -> None:

Version

0.14.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingruleImplementing or modifying a lint rule

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions