Запретить установку пакета на старые версии Python

Что мы можем положить в setup.py файл для предотвращения сбора pip и попытки установить пакет при использовании неподдерживаемой версии Python?

Например magicstack это проект, перечисленный с помощью классификатора trove:

Programming Language :: Python :: 3 :: Only

Так что я ожидаю следующего поведения, если pip --version привязан к питону 2.7:

$ pip install magicstack
Collecting magicstack
  Could not find a version that satisfies the requirement magicstack (from versions: )
No matching distribution found for magicstack

Но на самом деле pip собирает релиз, загружает его, пытается установить и терпит неудачу. Есть и другие релизы только для Python3, curio например, который на самом деле установить нормально - потому что setup.py не использовал ничего специфичного для Python3- только для сбоя во время импорта, когда используется только один синтаксис Python 3. И я уверен, что есть пакеты, которые устанавливают нормально, импортируют нормально, и, возможно, только сбой во время выполнения!

Какой правильный способ указать поддерживаемые версии Python таким образом, чтобы pip уважал? Я нашел обходной путь, включающий загрузку только файла колеса и отказ от загрузки дистрибутива.tar.gz, но мне было бы интересно узнать правильное исправление.


Редактировать: Как pip узнает, что не нужно загружать дистрибутив колеса, если Python / os / архитектура не совпадает? Использует ли он просто соглашение об именах.whl или есть что-то более изощренное, чем то, что происходит за кулисами? Можем ли мы как-то передать метаданные в исходный дистрибутив, чтобы pip правильно делал с загрузками.tar.gz?

2 ответа

Решение

Существует правильный способ сделать это, но, к сожалению, pip начал поддерживать его только в версии 9.0.0 (выпущена 2016-11-02), и поэтому пользователи с более старыми версиями pip будут продолжать загружать пакеты по воле, независимо от того, какой Python версия они для.

В вашем setup.py файл, пароль setup() python_requires аргумент, который перечисляет поддерживаемые версии Python вашего пакета в качестве спецификатора версии PEP 440. Например, если ваш пакет предназначен только для Python 3+, напишите:

setup(
    ...
    python_requires='>=3',
    ...
)

Если ваш пакет предназначен для Python 3.3 и выше, но вы еще не готовы перейти на поддержку Python 4, напишите:

setup(
    ...
    python_requires='~=3.3',
    ...
)

Если ваш пакет предназначен для Python 2.6, 2.7 и всех версий Python 3, начиная с 3.3, напишите:

setup(
    ...
    python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4',
    ...
)

И так далее.

После того, как вы это сделаете, вам нужно будет обновить версию setuptools как минимум до 24.2.0, чтобы python_requires аргумент для обработки; более ранние версии просто проигнорируют это с предупреждением. Все созданные после этого sdists и колеса вашего проекта будут содержать соответствующие метаданные, которые сообщают PyPI сообщить pip, для каких версий Python они предназначены.

magicstack распределение по pypi нарушено. Это сбой, потому что исходный дистрибутив не содержит magicstack пакет, хотя setup.py за исходный дистрибутив говорит, что должен.

Пока Pypi содержит исходный дистрибутив (например, .tar.gz, .zip), pip скачает это, если не может найти соответствующий бинарный дистрибутив (например, .egg, .whl) для вашей версии Python/ OS / архитектуры.

Вы можете загружать только двоичные дистрибутивы в pypi (желательно wheels), хотя я даже не знаю, разрешены ли только двоичные пакеты pypi. Другой вариант - проверить sys.version в вашем setup.py для совместимых версий и выдвиньте исключение в противном случае.

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