Подготовка и публикация модуля Django
Этот материал рассчитан на тех, кто уже написал свой модуль для Django и хочет, чтобы его труд оценили.
Мы хотим пояснить, зачем нужно готовить пакет для Python. Мы столкнулись с тем, что некая наша библиотека уходит за ненадобностью, потому что сообщество открытого кода сделало подобную вещь хоть позже нас, но лучше.
Итак, для чего вам нужно опубликовать свой модуль:
- чтобы снискать славу в сообществе открытого кода;
- грамотно опубликованный модуль заведомо имеет хорошую организацию кода, снабжён тестами и документацией;
- оформляя свой модуль, вы показываете уважение в первую очередь коллегам, которым предстоит работать с вашим кодом, а также всем разработчикам, которым ваш код может быть полезен;
- наконец, самому приятно, если твой код выглядит красиво и ухоженно.
Требования к модулям
Насчёт организации кода каждый решает сам. При публикации каждый сам выбирает, на что обратить больше внимания, а что обойти. Мы опишем технологию выпуска модулей в нашей компании, которая, судя по практике, имеет право считаться удобной.
1. Зависимости
Все зависимости от других библиотек должны быть прописаны в setup.py. Зависимость от самой Django мы не прописываем, чтобы при установке её не скачивал setuptools.
2. Интернационализация
В модуле не должно содержаться ни строчки на русском. В идеале не должно быть комментариев и текстов коммита не на английском. Мы стараемся в общем придерживаться этого идеала. Ко всем модулям создаётся русская локаль, так что сразу заметно, если что то не переведено.
3. Тесты
Наше слабое место. Тем не менее мы категорически настаиваем на наличии тестов у сколь бы то ни было сложных модулей. Существует множество удобных фреймворков для тестов, от Selenium до webtest, пользуйтесь ими на здоровье.
4. Документация
Каждый наш модуль содержит как минимум описание в README. Если модуль требует большей документации, то её необходимо предоставить пользователю.
5. Контроль версий
Мы долго размышляли о том, как публиковать версии того или иного модуля. Мы используем трёхзначную систему именования версий: [0].[мажорный релиз].[минорный релиз].
Вместо нуля первой цифрой станет единица, когда мы посчитаем модуль стабильным и неизменным. В репозитории мы делаем так: для мажорных версий созданы ветки, а для минорных создаются тэги. Это сделано для того, чтобы при использовании одной и той же мажорной версии модуля можно было получить исправления ошибок в минорных версиях.
Чем мажорные версии отличаются от минорных, спросите вы. Между двумя мажорными версиями сохраняется API и структура базы данных. Минорные версии могут добавлять новые возможности и исправлять ошибки.
Стандарт оформления
Мы стараемся оформлять модули по одному алгоритму. В корень проекта добавляются в обязательном порядке следующие файлы:
MANIFEST.in— файл для подключения медиа файлов в проект;README.rst— файл с кратким описанием и примерами применения модуля;README— символическая ссылка наREADME.rst. Именно такая, потому что хочется видеть документацию и на гитхабе, и в Python Package Index;DESCRIPTION— такое описание модуля, чтобы человек не в теме понял, для чего нужен этот модуль;setup.py— файл установщика.
Помимо этого, в файле __init__.py модуля должна быть переменная __version__, которая содержит номер текущей версии модуля, например:
__version__ = '0.1.0'
Текст README проверяйте на валидность reStructuredText, иначе в Python Package Index форматирование не будет отображаться и документация будет в текстовом виде.
Пример MANIFEST.in
Файл MANIFEST.in нужен для того, чтобы в пакет вошли медиа файлы: шаблоны, стили и скрипты.
include README README.rst DESCRIPTION INSTALL.txt
exclude *.orig *.pyc
Пример setup.py
setup.py по сути самый главный файл при публикации модуля. Он определяет всю мета информацию о пакете, разработчике, лицензии и файлах модуля.
import os
from setuptools import setup, find_packages
def read(fname):
try:
return open(os.path.join(os.path.dirname(__file__), fname)).read()
except IOError:
return ''
setup(
name="redsolutioncms.django.example",
version=__import__('myapp').__version__,
description=read('DESCRIPTION'),
license="GPL",
keywords="django tag1 tag2",
author="John Doe",
author_email="[email protected]",
maintainer='John Doe',
maintainer_email='[email protected]',
url="http://github.com/redsolution/myapp",
packages=find_packages(exclude=['example', 'example.*']),
install_requires=[],
include_package_data=True,
zip_safe=False,
long_description=read('README'),
entry_points={
'redsolutioncms': ['myapp = myapp.redsolution_setup', ],
}
)
Приведём комментарии к некоторым строкам. Данный setup.py подразумевает, что файлы README и DESCRIPTION существуют. Если это не так, описание будет пустым. Более того, версия будет пустой, если в __init__.py не будет переменной __version__.
Строка packages=find_packages(exclude=['example', 'example.*']) говорит о том, что если в модуле есть папка example и она является питоновским модулем, то её нужно исключить из пакета. Представьте, если дюжина модулей будет импортировать один и тот же модуль example.
Параметр entry_points нужен для интеграции с Redsolution CMS, об этом в статье про интеграцию. Полную спецификацию по параметрам можно найти на сайте разработчика setuptools. Мы наблюдаем тенденцию отчуждения от setuptools в пользу pip, однако мы остановили выбор на стабильной и проверенной библиотеке.
Публикация
Опубликовать модуль в Python Package Index очень легко. В первую очередь вам нужен будет аккаунт в Python Package Index. Затем зайдите в папку проекта и наберите:
python setup.py register
Для вас создастся страничка проекта. Для загрузки пишите:
python setup.py sdist upload
Готово! Ваш модуль в Python Package Index, можете проверять главную страницу.