Phil-ZXX
Phil-ZXX

Reputation: 3265

Flake8 gives F832 Undefined Name despite using "from __future__ import annotations"

I have this pyi file.

from __future__ import annotations
import datetime


class Payment:
    amount: float = ...
    date: datetime.date = ...

    def set_amount(self: Payment, amount: float = Amounts.Null):
        ...

    def get_amount(self: Payment) -> float:
        ...

    def get_date(self: Payment) -> datetime.date:
        ...


class Amounts:
    Null: float = ...

Using from __future__ import annotations helps remove the F821 undefined name 'Payment' warnings for the self arguments.

However, flake8 still shows F821 undefined name 'Amounts'. Can this warning be fixed somehow (without disabling F821 entirely)? Or it this a bug perhaps?


Note, I am using flake8 4.0.1 (mccabe: 0.6.1, pycodestyle: 2.8.0, pyflakes: 2.4.0) on Python 3.10.0.

Upvotes: 0

Views: 1249

Answers (1)

anthony sottile
anthony sottile

Reputation: 69972

the error is not wrong:

$ python3 t.pyi
Traceback (most recent call last):
  File "t.pyi", line 5, in <module>
    class Payment:
  File "t.pyi", line 9, in Payment
    def set_amount(self: Payment, amount: float = Amounts.Null):
NameError: name 'Amounts' is not defined

__future__ annotations defers annotations but you've got a default value (which is not an annotation!) referring to a class later in the file

one option is a simple reordering:

from __future__ import annotations
import datetime


class Amounts:
    Null: float = ...


class Payment:
    amount: float = ...
    date: datetime.date = ...

    def set_amount(self: Payment, amount: float = Amounts.Null):
        ...

# ...

even better is to omit the default value entirely, since it does nothing in a pyi (or stub function):

from __future__ import annotations
import datetime


class Payment:
    amount: float = ...
    date: datetime.date = ...

    def set_amount(self: Payment, amount: float = ...):

# ...

note also that your function is subtly incorrect -- right now a type checker will interpret set_amount as -> Any because you omit the return value, the correct thing to do there is -> None

the other route you can take is to ignore the errors via # noqa, per-file-ignores, or other means -- though that's probably not what you want to do since the code as-is is broken


disclaimer: I currently maintain flake8

Upvotes: 2

Related Questions