Что делать, если нужный вам модуль поддерживает только Python 2: пошаговое руководство

Что делать, если нужный вам модуль поддерживает только Python 2: пошаговое руководство

Перед вами небольшая инструкция по решению довольно распространенной проблемы: при работе над проектом оказывается, что один из необходимых вам модулей не поддерживает Python 3. Для примера взята клиентская библиотека для Qualys (средство обеспечения безопасности). Вот что вам следует сделать:

0. Удостовериться, что этот вопрос еще не решен

Прежде чем начать, проверьте, не сталкивался ли кто-то ранее с такой же проблемой, исследуйте GitHub. Посмотрите — может быть, на PyPi найдется подходящий пакет, в котором содержатся обновления для Python 3.

1. Сделать форк

Если поиски все же ни к чему не привели, приступайте к изменению выбранного модуля. Стоит заметить, что обычно на PyPi указываются поддерживаемые версии Python. У модулей, работающих только с Python 2, данная информация часто бывает опущена. В рассматриваемом примере эта часть описания модуля выглядит следующим образом:

Итак, откройте основной проект на GitHub. Прежде чем вносить любые изменения, обязательно создайте его форк, затем скачайте или клонируйте репозиторий и создайте новую ветку. Говорящим названием для неё будет, например, «python3».

Если вам неясно, как проделать эти действия, читайте наше руководство по Git для новичков.

2. Исправить операторы print

Первое, с чем нужно разобраться до решения проблем с импортированием — это самые обычные операторы вывода. Старые операторы print без скобок — одно из самых распространенных препятствий, с которым можно столкнуться в контексте перехода от Python 2 к Python 3. В третьем шаге мы будем использовать пакет Python-Modernize, облегчающий этот переход, но его работа не затронет README, документацию и некоторые другие файлы. Чтобы найти абсолютно все старые операторы print в пределах модуля, воспользуйтесь рекурсивным поиском по вложенным директориям:

Вы увидите, что некоторые из выведенных на экран соответствий находятся в директории git , игнорируйте их. Все остальные найденные операторы print замените на функции print() в любом текстовом редакторе, а после создайте из исправлений единый коммит командой:

3. Провести тесты

«Лучший» способ проверить совместимость Python 2 и 3 — через полное тестирование и CI сервисы вроде Circle, Snap или Travis. Но вот незадача — для модернизируемого вами модуля никаких тестов нет. И у вас остается два варианта:

  • написать тесты самому;
  • провести статический анализ кода.

Если вы сомневаетесь, что второй вариант может вам чем-то помочь, прочитайте нашу статью о статическом анализаторе.

Статический анализ. Установите Python-Modernize:

Сначала запустите его в режиме info:

Это позволит получить общее представление о том, какие изменения будут внесены. Все устраивает? Тогда запускайте процесс изменений следующей командой:

Затем сделайте из них отдельный коммит.

Добавление тестов. Первая проверка: можно ли импортировать модуль, пакет, подмодуль? Этот тест вскрывает много проблем в Python 3, связанных с пространствами имен. Используйте Tox для проведения тестирования в различном окружении.

Вторая проверка: есть ли в проекте обработка строк. На тему строк в Python 3 информации гораздо больше, чем можно уместить в этом посте, но вы можете обратиться к проекту six, в котором рассматривается проблема определения, является ли объект строкой, а также использование юникода и методов байтовой конвертации.

Третья проверка подразумевает наличие некоторого опыта в работе с модулем. Вы не сможете сразу заняться юнит-тестированием на основе существующей кодовой базы, если не будете понимать, насколько корректно она работает на данный момент. Двигайтесь в обратном направлении — сфокусируйтесь на интеграционном тестировании, а от него перейдите к юнит-тестам. Попробуйте для начала написать простой скрипт, который использует модуль по его прямому назначению, а затем дополняйте его другими сценариями использования. Если вы уже настроились пропустить данную проверку, почитайте наш материал о пользе юнит-тестирования.

4. Обновить setup.py

Откройте setup.py и посмотрите, какие изменения в него нужно внести, чтобы уверенно заявлять, что рассматриваемый нами модуль теперь поддерживает Python 3:

На что точно стоит обратить внимание:

  1. В коде выше обнаружилось как указание лицензии BSD, так и лицензии Apache 2. При этом в кодовых файлах говорится Apache 2, а в директории вообще нет файла LICENSE. Такая ситуация могла возникнуть из-за ошибки, связанной с копипастом, поэтому в данном случае её логично исправить в setup.py, а потом добавить соответствующий файл LICENSE.
  2. Разметка в PyPi не отображается. Можно с этим смириться, можно добавить RST файл. Главное, помните о том, что это все же не ваш проект.
  3. Не написано, какую версию Python поддерживает модуль. Добавьте эту информацию в setup.py.
  4. Использование Python-Modernize означает, что данный модуль зависим от пакета six. Отметьте это в поле install_requires . А заодно проверьте, что все указанные там пакеты, от которых зависит изменяемый модуль, тоже поддерживают Python 3.

Посмотрим, что получилось:

5. Загрузить в основной проект

Вернемся к началу. При работе над вашим проектом вы столкнулись с тем, что один из модулей не поддерживает Python 3. Вы избавились от проблем совместимости, теперь нужно указать обновленную версию модуля в файле requirements.txt . Убедитесь в том, что вы сначала запушили изменения на GitHub. Это делается командой:

Pip позволяет вам устанавливать необходимое не только из PyPi, но и прямо из репозитория Git. Вы можете указать конкретную ветку, используя символ @. Параметр egg= используется, чтобы передать Pip имя пакета.

На этом этапе можно продолжить запуск интеграционных тестов для новой версии.

6. Отправить пулл реквест

Теперь нужно поделиться своей работой с автором и сообществом Python на GitHub. Придерживайтесь следующих правил общения:

  1. Будьте вежливы.
  2. Поясните, что хотели бы использовать этот модуль с Python 3.
  3. Поблагодарите автора за его работу по созданию модуля.
  4. Прокомментируйте, что сделали.

Вот такой пулл реквест получился по итогам рассмотренного примера. Подождите, пока ваши изменения зальют в проект, после чего ожидайте, когда на PyPi появится обновление. (Вернее, надейтесь, что оно там появится.)

📎📎📎📎📎📎📎📎📎📎