2017-02-15 19 views
7

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

Например magicstack проект перечислены с кладом классификаторе:

Programming Language :: Python :: 3 :: Only 

Так что ожидать следующее поведение, если pip --version привязан к Python 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 не использовал ничего конкретного Python 3 - только для отказа при импорте, когда используется только синтаксис Python 3. И я уверен, что есть пакеты, которые устанавливают ОК, импортируют ОК и, возможно, только сбой во время выполнения!

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


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

+0

Я не знаю, что это _right_ ответ ... но если 'magicstack' является python3 только потому, что' setup.py' не работает на python2.x, то кажется, что один из возможных способов сделать эту работу заставьте ваш 'setup.py' терпеть неудачу на неподходящих версиях python ... – mgilson

+0

Hacky. Если pip привязан к неподдерживаемому интерпретатору Python, я не хочу, чтобы пакет был собран или загружен вообще, не говоря уже о попытке установки, выполнив 'setup.py'. – wim

+0

Google раскрывает некоторые [предыдущие] (http://stackoverflow.com/questions/13924931/setup-py-restrict-the-allowable-version-of-the-python-interpreter) [вопросы] (http: // stackoverflow .com/questions/13385337/distribute-distutils-define-python-version) с ответами, говорящими о том, что ваша 'setup.py' проверяет версию Python. – user2357112

ответ

3

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

В файле setup.py, передать setup() в python_requires аргумент, который содержит список поддерживаемых версий Python своего пакета, как PEP 440version specifier. Например, если ваш пакет для 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, чтобы сообщить, для каких версий Python они предназначены.

+0

Привет, спасибо за обновление. Я попробовал ваше решение, но оно не работает должным образом. Я обновил setuptools до v34.3.2 и загрузил новые дистрибутивы с помощью 'python_requires' kwarg. С пипеткой версии 9.0.1 на Python 3.6 поведение ** корректно ** (pip отказывается загружать/выполнять дистрибутив и печатает нужные/фактические версии python). Однако, используя pip версии 9.0.1 на Python 2.7, это неверно - дистрибутив загружается и выполняется 'setup.py'. Кажется, что есть соответствующие метаданные (поскольку это работает для pip3), но pip2 игнорируется. Я что-то упускаю? – wim

+0

@wim: Какой спецификатор спецификации вы использовали для 'python_requires'? – jwodder

+0

Я использовал 'python_requires> = '3.6.1'', чтобы применить ограничение на метаданные, а затем протестировал pip 9.0.1, используя виртуальные среды в 3.6.0 и 2.7.5. – wim

1

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

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

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

+0

Разрешено только распространение двоичного кода, я на самом деле упомянул об этом в своем вопросе в качестве моего текущего обходного пути. См. [Toga-curses] (https://pypi.python.org/pypi/toga-curses/) для примера пакета, который будет устанавливаться с помощью pip3, но даже не увидит pip2. – wim