Getting NameError for annotation even if I use TYPE_CHECKING import

Viewed 1452

I have two classes with annotations / type hints.

First one works without any problem:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from bunyamin.models.exchange import Exchange

class Kline:

    def read_klines(exchange: Exchange):
        pass

Second one is really similar:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from bunyamin.models.timeframe import Timeframe

def normalize_dt(dt: datetime, timeframe: Timeframe) -> datetime:  # -> This line raises NameError
    pass

but raises NameError: name 'Timeframe' is not defined.

I know I can just use a string (like 'Timeframe') instead of the class itself, but AFAIK this is not the expected behavior. What am I missing?

Python version I'm using is 3.8.2, if that's relevant.

EDIT:

While I was trying to isolate the problem, I've omitted all of the "seemingly irrelevant" imports. But the first file actually contains from __future__ import annotations at the top, which makes it work. See the first answer for details.

2 Answers

When you use TYPE_CHECKING constant, function parameters annotations must be enclosed in quotes, making it a “forward reference”, to hide it from the interpreter at runtime, as timeframe: 'Timeframe'. Because these are evaluates at a time of function definition by default until Python 3.10, when postponed evaluation of annotation becomes the default.

I got it.

For isolating the problem, I've omitted the "seemingly" irrelevant imports on both classes. But I've just noticed that in the first file which contains Kline class, I've used from __future__ import annotations and in the second I did not, which postpones the evaluation of the annotations.

Reference can be found here:

https://www.python.org/dev/peps/pep-0563/

Note that from __future__ import annotations has to occur at the top of the file, or it raises a SyntaxError

Related