Ссылки mypy class forward в псевдониме типа выдают ошибку, когда в другом модуле

Я хочу сохранить псевдонимы типов в одном модуле, скажем my_types, чтобы иметь возможность использовать их где угодно в моем приложении (аналогично стандартному модулю typing). Но mypy жалуется, что прямая ссылка на класс X не определена. Если я определю класс X позже в том же модуле, это нормально, но если он определен в другом, mypy расстроится.

Итак, мой вопрос: как мне сохранить все мои псевдонимы типов в одном модуле, чтобы mypy не вызывал ошибку о прямых ссылках, которые не определены в том же модуле? Или это как-то неправильно?

Вот мой пример кода:

from my_types import SomeXs

class X:
    pass

Псевдонимы типов определяются так:

# my_types.py
from typing import List

SomeXs = List['X']

Когда я запускаю mypy, я получаю сообщение об ошибке X не определено:

$ mypy module.py
my_types.py:4: error: Name 'X' is not defined
Found 1 error in 1 file (checked 1 source file)

person fqxp    schedule 11.12.2020    source источник
comment
Попробуйте SomeXs = List[X]   -  person Hirusha Fernando    schedule 11.12.2020
comment
@HirushaFernando Это выдает ошибку с неопределенным именем.   -  person fqxp    schedule 11.12.2020
comment
Не совсем понятно, о чем вы спрашиваете. Если класс X не входит в my_types (через определение или импорт), то X, 'X' и любые другие подобные варианты не могут ссылаться на него. Это не имеет ничего общего с форвардными объявлениями, которые обращаются к более поздним привязкам в той же области. Как вы ожидаете, что MyPy узнает, что X означает module.X, а не какой-то другой X? Возможно, вы ищете TypeVar?   -  person MisterMiyagi    schedule 11.12.2020
comment
@MisterMiyagi Это указывает на интересное направление, я не думал о том, что mypy нужно знать об определении типа, о котором я говорю, а не только о том, что он называется X.   -  person fqxp    schedule 11.12.2020


Ответы (2)


Я поделюсь решением, которое нашел в документации mypy раздел распространенных проблем здесь: mypy необходимо иметь доступ к определению X. Чтобы избежать цикла импорта, документация mypy рекомендует трюк - импортировать только определение, которое будет создавать циклический импорт при проверке типа. Это выглядит так:

from typing import List, TYPE_CHECKING

if TYPE_CHECKING:
    from main import X

SomeXs = List['X']

Это заставляет интерпретатор Python игнорировать импорт при выполнении этого кода, но mypy по-прежнему использует определение X из main.

И вуаля:

$ mypy *.py
Success: no issues found in 2 source files
person fqxp    schedule 12.12.2020

Mypy должен иметь ссылочные типы в области видимости:

$ cat my_types.py 
from typing import List

from main import X

SomeXs = List[X]

И код, содержащий X, не ссылается на SomeXs, поэтому его не следует импортировать туда:

$ cat main.py 
class X:
    pass

Результат:

$ mypy .
Success: no issues found in 2 source files
person l0b0    schedule 11.12.2020
comment
Спасибо, но это был только тестовый пример. Мне нужен тип SomeXs в main.py, поэтому это решение не поможет. - person fqxp; 12.12.2020