Как правильно настроить MYPYPATH, чтобы подобрать заглушки для mypy? - PullRequest
2 голосов
/ 31 марта 2019

Я не могу заставить MyPy найти заглушки, которые не связаны с их исходным кодом. Вот структура, которая у меня есть для моего проекта:

trymypy/
|- stubs/
|  \- foo.pyi
|- __init__.py
|- usefoo.py
\- foo.py
# foo.py
def foofunc(x):
    return str(x)
# usefoo.py
from trymypy.foo import foofunc

print(foofunc(5) + 5)
# stubs/foo.pyi
def foofunc(x: int) -> str: ...

Я установил переменную окружения MYPYPATH на /full/path/to/trymypy/stubs, чтобы MyPy просматривал каталог stubs для моих файлов .pyi.

Это не должно проходить проверку типов. MyPy должен пометить ошибку следующим образом:

../trymypy/usefoo.py:3: error: Unsupported operand types for + ("str" and "int")

Вместо этого MyPy не помечает никаких ошибок, поскольку не читает заглушки. Если я перенесу файл-заглушку foo.pyi в корневой проект каталога, связанный с foo.py, он правильно помечается, что указывает на то, что MYPYPATH не берется или не определяется правильно .

Я также попытался установить mypy_path в файле конфигурации mypy.ini:

[mypy]
python_version = 3.7
mypy_path = /full/path/to/trymypy/stubs

Другие параметры конфигурации в mypy.ini действительно выбираются (например, python_version), поэтому MyPy просматривает файл и читает его.

Совершенно озадачен здесь. Это (очень) простой пример, который, кажется, должен работать так, как задокументировано MyPy. У меня закончились переменные, чтобы поэкспериментировать, чтобы он заработал.

Я использую Python 3.7 и работаю в виртуальной среде, в которой установлен только mypy.

1 Ответ

1 голос
/ 31 марта 2019

Короче говоря: вместо того, чтобы иметь отдельный каталог 'stubs', вы, вероятно, захотите переместить файл foo.pyi в папку trymypy верхнего уровня вместе с foo.py.


* 1006.* Длинная история, в настоящее время есть две проблемы с вашей настройкой.

Первая проблема заключается в том, что структура папок ваших заглушек должна отражать структуру базового кода.Так как вы хотите сделать from trymypy.foo import blah, вам нужно настроить структуру папок так, чтобы она выглядела следующим образом:

trymypy/
|- stubs/
|  |- trymypy/
|  |  |- __init__.pyi
|  \  \- foo.pyi
|- __init__.py
|- usefoo.py
\- foo.py

Вы должны продолжить установку mypypath, чтобы указать trymypy/stubs.Вы можете использовать как абсолютный, так и относительный путь.

Вторая большая проблема в том, что ваши заглушки могут оказаться в тени и игнорироваться в зависимости от того, как именно вы вызываете mypy.Например, если вы запустите mypy -p trymypy из-за пределов папки trymypy, mypy начнет с анализа каждого trymypy и двух подмодулей, которые он содержит непосредственно (trymypy.__init__, trymypy.usefoo и trymypy.foo).

И после загрузки trymypy.foo mypy не будет пытаться снова загрузить его, а это значит, что он не будет беспокоиться о проверке заданных вами заглушек.

Но если вы попробуете проверить тип отдельнофайлы (например, mypy -m trymypy.usefoo, mypy -p trymypy.usefoo), mypy не будет пытаться загрузить все внутри trymypy, что означает, что он может найти заглушки, используя типичные правила разрешения импорта .

Вы можете подтвердить поведение всего этого самостоятельно, передав флаг -v, который запускает mypy в подробном режиме и распечатывает именно то, что загружается.Обязательно удаляйте каталог .mypy_cache перед каждым запуском.

Примечание. На самом деле я честно не знаю, является ли это различие в поведении преднамеренным или ошибка в mypy.Правила импорта довольно тонкие.


Исправление, к счастью, простое: просто переместите файл foo.pyi в папку верхнего уровня trymypy, например, так:

trymypy/
|- __init__.py
|- usefoo.py
|- foo.py
\- foo.pyi

Теперь, независимо от того, что импортируется в каком порядке, mypy всегда найдет foo.py и foo.pyi одновременно, так как оба файла находятся в одном каталоге.И всякий раз, когда файлы py и pyi находятся в одном и том же каталоге, файл pyi всегда побеждает (а файл py игнорируется).


Возможно, у вас есть два следующихвопросы относительно этой новой структуры папок:

  1. Есть ли способ проверить тип содержимого foo.py, используя подсказки типа, представленные в foo.pyi?

    Ответ - нет, там в настоящее время нет пути.Если у вас есть foo.pyi, mypy по существу игнорирует тело foo.py.Есть кто-то, кто заинтересован в добавлении поддержки этой функции , поэтому вы можете подписаться на связанную проблему Github для обновлений.

  2. Создайте отдельную папку "заглушки"в конечном итоге бесполезно здесь.Поэтому, когда это , это полезно?

    Ответ заключается в том, что это в первую очередь полезно, когда вы хотите добавить заглушки для сторонних библиотек.На самом деле у меня нет большого опыта работы с процессом «добавить заглушки для вашего собственного кода», но я понимаю, что такие заглушки обычно «встроены», как описано выше.

...