Как запустить mypy на коде, чувствительном к версии стороннего пакета

В настоящее время я отвечаю за написание кода библиотеки, совместимого с pydantic v1 и v2.

Обеспечение функциональности кода более или менее просто, поскольку вы можете сделать в своем коде выбор, чувствительный к версии, чтобы удовлетворить требованиям вашего набора тестов, например используя такие шаблоны:

import pydantic

PYDANTIC_VERSION = packaging.version.parse(pydantic.__version__)

if PYDANTIC_VERSION.major == 1:
    # do some v1 things
else:
    # do some v2 things

Однако добиться совместимости этого кода с проверками типов mypy кажется трудным, поскольку mypy не разрешает переменную PYDANTIC_VERSION и всегда проходит через обе стороны блоков if. Это будет постоянно вызывать ошибки mypy в обоих мирах внутри нашего CI (где mypy должен работать с обеими версиями).

Это имеет смысл, поскольку mypy не является средством проверки типов во время выполнения, но мне интересно, существуют ли какие-либо передовые методы для достижения такой цели.

На самом деле эта проблема не уникальна для pydantic, это всего лишь пример. Я знаю, что такие переключатели версий работают с версией интерпретатора (sys.version_info), но я не могу найти способ заставить mypy пропускать весь блок кода, если версия pydantic равна 1.x.x или 2.x.x

Я искал проблемы на mypy и Stack Overflow, но, учитывая тысячи проблем и статей, очень сложно найти существующие (в конечном итоге решенные или исправленные) подробности по этой теме.

Потенциально полезно: mypy.readthedocs.io/en/stable/…

Brian61354270 16.04.2024 15:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

--always-true и --always-false существуют, поэтому вы можете создать логический флаг с именем PYDANTIC_V1 и дважды запустить Mypy с одним и тем же кодом:

$ pip install "pydantic==1.*"
$ mypy file.py --always-true=PYDANTIC_V1
$ pip install -U pydantic
$ mypy file.py --always-false=PYDANTIC_V1

Ух ты, звучит прекрасно, никогда не видел этих флагов. Я обязательно попробую это и загляну сюда, сработало ли это!

ddluke 16.04.2024 19:32

Очевидно, это правильный путь: обеспечить совместимость типизации с двумя основными версиями библиотеки по-прежнему сложно, но флаги --always-true/false определенно являются правильным решением. Большое спасибо!

ddluke 24.04.2024 07:38

Другие вопросы по теме