Создание своего локального PyPI репозитория

 

Создать свой PyPI репозиторий для рабочего проекта мне пришлось сразу по нескольким причинам: начиная от архитектурных особенностей, заканчивая простотой удобством такого решения. Началось все с того, что наше приложение состоит из набора независимых между собой частей, packages. Соответственно, каждый такой пакет может зависить от любого числа других - как самописных так и нет. В таком случае создавать для каждого пакета свой файл pip-requirements для разворачивания окружения стало сложно и неудобно. Следующая причина - это сделать возможность установки любого пакета нужной верисии не имея доступа к нашей системе контроля версий (mercurial). Все-таки набрать команду “pip install my-package-name” намного проще и быстрее, чем указывать путь к исходникам или source control. И последняя причина для меня была в том, что необходимо следить за всеми зависимостями к внешним библиотекам: не только использовать нужную версию, устанавливать пропатченную, но и иметь список всего используемого в проекте (с этим пунктом возникло больше всего трудностей).

И так, что же представляет собой любой PyPI репозиторий? В простейшем случае - это папка с пакетами. Но для более легкого использования все же удобнее использовать веб-сервер. Так же можно использовать любой, но есть и специально написанные для этого приложения, которые имеют ряд примуществ. Я для себя пока остановился на pypiserver (http://pypi.python.org/pypi/pypiserver). Он достаточно простой, но при этом может работать как stand alone приложение или wsgi приложение с разными веб-серверами. Из недостатков, которые сразу бросились в глаза - это лишь то, что он не поддерживает upload пактов, т.е. команда “python setup.py upload” с ним работать не будет, но это автор обещает исправить в следующих версиях.

Установка pypiserver, самом простом случае выглядит так:

 

  • $ pip install pypiserver
  • $ mkdir ~/packages
  • копируем нужные пакеты в папку ~/packages и запускаем сервер:
  • $ pypi-server -p 8080 ~/packages

 

После чего репозиторий будет доступен по ссылке http://localhost:8080/simple/.

Теперь собственно про создание своих пакетов. С этим хорошо справляется ditsutils, которые идут вместе с Python (к сожалению, не так хорошо, как это будет в Python 3.3).

Для начала создаем в нашем пакете файл setup.py. В простейшем случае он будет выглядеть примерно так:

setup(name=‘package-name’,      version=‘0.2.1’,      description=‘description’,      author=‘e0ne’,      author_email='e0ne@e0ne.info,      url=‘http://blog.e0ne.info’,      packages=[‘package_name’, ],     )

 

Далее создаем дистрибутив нашего пакета. В моем случае это только питоновские модули, поэтому меня вполне устроил sources distrib:

**$ python setup.py bdist **

Эта команда создаст каталог dist и положит туда архив с дистрибудивом пакета, который, в моем случае, нужно положить в ~/packages. После чего остается лишь выполнить команду для его установки:

$ pip install package-name -i http://localhost:8080/simple

Для более простого использования можно переопределить переменную окружения PIP_INDEX_URL, чтобы еще упростить вызов команды:

$ export PIP_INDEX_URL=http://localhost:8080/simple/$ pip install package-name

Следующим шагом что нужно сделать - это автоматизировать процесс создангия и выкладывания на свой PyPI-сервер пакетов путем интеграции с continuous integration (CI) сервером. Но так, как это сильно зависит от проекта, выбора CI и структыры исходного кода - приводить пример сдесь не буду. Кому нужно сможет сделать это сам или задать нужные вопросы в комментариях.

И последняя проблема у меня заключалась в том, что нужно полностью отказаться от http://pypi.python.org/pypi по двум причинам: ускорить процесс сборки билда путем удаления необходимости выкачивать нужные зависимости с интернета и иметь полный список всех зависимостей. При этом делать полное зеркало не хотелось. Как оказалось, в Python 2.7 сделать это не так уж и просто (на досуге нужно будет посмотреть как там с этим в Python 3.3). Проблема в том, что pip installer, который у нас используется устанавливает пакеты с помощью стандартных setuptools, что практически аналогично вызову команды “python setup.py install”. И если в setup.py есть строки типа install_requires=’django’, то setuptools не найдет это в локальном репо полезет в интернет. Заставить его работать по-другому без фикса кода можно несколькими способами. Самые простые - это:

 

  • добавить запись в /etc/hosts вида “127.0.0.1    pypi.python.org
  • настроить прокси-сервер для блокирования доступа к pypi.python.org с билд-машины.

 

Методы кардинальные, но работают. При этом поломанные билды из-за отсутствия нужного пакета в локальном репозиории лежат полностью на совести разработчиков.

Ссылки по теме:

 

 

 

 

 

Tags

.net .net-framework .net-framework-3.5 agile ajax ajax-control-toolkit ampq ansible apache asp.net asp.net-mvc automation axum babel bash benchmark blog blog-engine bootstrap buildout c# cache centos chrome ci cinder ckan cli cloud code-review codeplex community config debugger deface dependencies development-environment devices devstack devtime disks django dlr dns docker dockerimage dos easy_install elmah encoding environment-variables error event events everything-as-a-code exception exceptions fabrik firefox flask foreach forms fstab gae gcc gerrit git github go google google-app-engine grep hack hacked hardware headless horizon hound html hugo iaas ienumerable iis internet iptables iron-python ironic iscsi java-script javascript jenkins jquery js jsx k8s kharkivpy kiss kombu kubernetes kvm kyiv lettuce libvirt linux lio loci logging loopback losetup lvm mac-os macos mercurial microsoft microsoft-sync-framework mobile mono ms-office msbuild networking news nginx npm npx offtopic oop open-source open-xml opensource openstack openvswitch os packages paraller-development patterns-practices performance php pika pip plugins pnp podcast popup postgresql profiler project protocols proxy pycamp pycharm pycon pykyiv pylint pypi python python-3 qcow quantum qumy rabbitmq rar react reactjs refactoring rfc rhel search-engine security selenium server shell silverlight socket software-engineering source-control sourcegear-vault sources sql sql-server sql-server-express sqlalchemy ssh static-site sublimetext svg tests tgt tipfy todo tornado typescript uapycon ui uneta unit-tests upgrades usability vim virtualenv visual-studio vitrage vm vue.js vuejs web-development web-server web-service web_root webpack webroot windows windows-live word-press x32 x64 xcode xml xss xvfb интернет-магазин книги

Recent posts

Go 1.18: new features

Всё будет Kubernetes

2022 Relaunch

Everyday Blogging

I don't want this CI


Archives

2022 (3)
2019 (73)
2018 (2)
2017 (3)
2016 (2)
2015 (3)
2014 (5)
2013 (17)
2012 (22)
2011 (36)
2010 (25)
2009 (35)
2008 (32)
2007 (2)