У меня есть два пакета Python (саранча-рой и плагины саранчи). Ни у одного из них нет строгих требований к другому, но они могут работать вместе, и мои пользователи устанавливают их отдельно.
Иногда есть критические изменения в одном или другом, и я хочу убедиться, что никто не устанавливает несовместимые версии (например, обновляя пакет A, но не пакет B). Есть ли способ указать минимальную версию этой «псевдозависимости» и отказаться от установки, если она не удовлетворена? Проверка, которая выполняется только в том случае, если другой пакет уже установлен.
Я не хочу добавлять один пакет в качестве зависимости от другого и заставлять пользователей пакета A устанавливать пакет B, просто чтобы справиться с этим случаем.
Возможно, этот вопрос уже задавался ранее, но я не нашел ответа.
Вероятно, вам нужно выполнить проверку совместимости версий во время выполнения. Что-то вроде if importlib.metadata.version('locust-plugins') < '1.2.3': raise IncompatiblePlugins()
(псевдокод).
Я думаю, что вы можете быть правы sinoroc. Или, может быть, это можно сделать в хуке после установки? (хотя это более приятно иметь)
В экосистеме пакетов Python нет «перехватчиков после установки». -- Вы можете попробовать задать свой вопрос здесь -- Интересно, существует ли то, что вы хотите сделать, в других экосистемах пакетов (Node, Rust, Java и т. д.), похоже, что это может быть "одноранговая зависимость в npm
.
Я не знаю, правильно ли я понимаю вопрос, но вы можете указать минимальную требуемую версию в массиве install_requires
в функции настройки следующим образом.
install_requires=['locust-swarm >= 1.2', 'locust-plugins >= 1.1']
Я надеюсь, что это отвечает на ваш вопрос, если это не так, дайте мне знать, и я буду изучать его дальше.
В вопросе говорится, что одно не может быть зависимостью другого. Так что мне кажется, что это не отвечает на вопрос.
Да, но я не думаю, что есть чистая альтернатива
Я думаю, вы можете сделать это в своем файле A/setup.py
(и то же самое в вашем файле B/setup.py
, просто измените package_B_name
на package_A_name
:
import importlib.util
spec = importlib.util.find_spec(f'{package_B_name}')
if spec is not None:
requirements_list.append(f'{package_B_name}> = {package_B_version}')
Обратите внимание, что это работает только в Python3.3+ и только в исходных дистрибутивах. Не будет работать при установке с бинарного колеса (.whl)
Звучит многообещающе и отлично работало, когда я выполнял локальную установку (pip install.), но я добавил это в locust-swarm (github.com/SvenskaSpel/locust-swarm/commit/…) и опубликовал его как 4.1. 0, и он ничего не требует :-/ Может требования "прожжены" в опубликованном пакете?
Вы можете добавить отпечатки и посмотреть, добавился ли пакет в список... все равно, если он работал локально, то похоже, что в новой версии что-то не так?
Хм. Интересно, что я изменил - теперь это работает :) Возможно, я уже установил locust-swarm из локальной сети, а затем установка из pypi на самом деле ничего не сделала, потому что моя текущая установка была новее. Спасибо! (я внес небольшое редактирование в ваш ответ - без него у меня появилось требование, которое на самом деле было списком символов :)
Нет, подождите, теперь он снова перестал работать :(
Ах. Думаю, теперь я понял. Чтобы это работало, это должен быть исходный дистрибутив (не двоичное колесо). Должно быть, однажды мне повезло, и я установил как раз в тот момент, когда моя сборка заканчивалась, и была загружена только исходная версия. Я проверю эту гипотезу (путем отключения бинарных пакетов) сегодня вечером.
Если вы знаете, как преобразовать файл requirements.txt в файл setup.py, попробуйте, например, следующее:
my-package>=minimum.version
Это проверяет, является ли пакет больше, чем эта конкретная версия, или это минимальная версия, поэтому создается минимальная версия.
Я не могу придумать решение для этого, так как между двумя вещами нет "отношения зависимости"... -- Возможно, вы могли бы взломать что-то вместе с "дополнительными/необязательными" зависимостями, которые сблизили бы вас, но я не думаю, что это действительно будет работать достаточно хорошо.