Если вы хотите написать плагин для bzr, но не знаете с чего начать, то эта статья для вас. В этой статье я кратко расскажу об основных моментах разработки плагинов, которые вам нужно/полезно знать.
Для успешной разработки плагина нужно знать и понимать следующие вопросы: как плагины загружаются при запуске bzr, как плагины взаимодействуют с кодом bzr, как плагин может расширять существующую функциональность bzr, как организовать код плагина. Есть также ряд менее важных сопутствующих вопросов: как распространять/устанавливать плагины, как писать тесты для плагинов.
Язык программирования
Bazaar написан на языке программирования Python. Плагины очень тесно взаимодействуют с кодом самого bzr, поэтому они также должны быть написаны на Python.Документация и примеры
При разработке плагинов вам поможет следующая документация:
- Прежде всего полезно ознакомиться с кратким учебником по разработке плагинов: http://bazaar-vcs.org/WritingPlugins
- Чтобы узнать о методах использования библиотеки bzrlib для выполнения типичных операций, используйте документ http://bazaar-vcs.org/Integrating_with_Bazaar
- Подробнее узнать о поддерживаемом API плагинов можно из документа http://doc.bazaar-vcs.org/bzr.dev/developers/plugin-api.html
- Хуки и их сигнатуры приведены в документе http://doc.bazaar-vcs.org/bzr.dev/en/user-reference/bzr_man.html#hooks
- В качестве справочника по bzrlib API можно использовать автоматически сгенерированную API-документацию: http://starship.python.net/crew/mwh/bzrlibapi/
Как bzr загружает плагин
Код загрузки плагинов содержится в модуле bzrlib/plugin.py
При старте bzr производит поиск питон-модулей и питон-пакетов в предопределенных каталогах (~/.bazaar/plugin, site-packages/bzrlib/plugin и т.п., подробнее см. статью "Плагины bzr: основные сведения" раздел "Как подключить плагин").
Для всех найденных модулей и пакетов делается попытка импорта (в терминах Python). При импорте Python исполняет импортируемый код, поэтому вся инициализация плагина и регистрация новых команд/функций/форматов/хуков должна производиться в момент импорта. Сам bzr в момент загрузки плагина не вызывает никаких функций из импортируемого модуля.
В случае успешного импорта плагин регистрируется для последующего использования.
При старте bzr производит поиск питон-модулей и питон-пакетов в предопределенных каталогах (~/.bazaar/plugin, site-packages/bzrlib/plugin и т.п., подробнее см. статью "Плагины bzr: основные сведения" раздел "Как подключить плагин").
Для всех найденных модулей и пакетов делается попытка импорта (в терминах Python). При импорте Python исполняет импортируемый код, поэтому вся инициализация плагина и регистрация новых команд/функций/форматов/хуков должна производиться в момент импорта. Сам bzr в момент загрузки плагина не вызывает никаких функций из импортируемого модуля.
В случае успешного импорта плагин регистрируется для последующего использования.
Взаимодействие плагина с bzrlib
Плагины должны регистрировать новые команды и функции императивным способом: путем вызова соответствующих функций из bzrlib. Т.е. код плагина импортирует соответствующие модули/функции из bzrlib и затем вызывает их с необходимыми аргументами.
Практически для всех точек расширения в bzrlib используются реестры объектов. API объектов-реестров находится в модуле bzrlib/registry.py. Однако, часто регистрация расширений производится и при помощи специальных функций. Так, например, функция регистрации новых команд register_command находится в модуле bzrlib/commands.py. API для регистрации хуков определено в модуле bzrlib/hooks.py, однако сами хуки регистрируются для классов Branch (bzrlib/branch.py), BzrDir (bzrlib/bzrdir.py) и проч.
Практически для всех точек расширения в bzrlib используются реестры объектов. API объектов-реестров находится в модуле bzrlib/registry.py. Однако, часто регистрация расширений производится и при помощи специальных функций. Так, например, функция регистрации новых команд register_command находится в модуле bzrlib/commands.py. API для регистрации хуков определено в модуле bzrlib/hooks.py, однако сами хуки регистрируются для классов Branch (bzrlib/branch.py), BzrDir (bzrlib/bzrdir.py) и проч.
Данная статья не ставит перед собой целью дать исчерпывающее описание всех точек расширения в bzrlib. Мы постараемся осветить эти вопросы в других статьях на живых примерах. Однако помните о том, что для bzr написано множество плагинов, которые можно использовать в качестве наглядного примера использования точек расширения.
Советы по организации кода плагина
Плагин может быть одиночным модулем или питон-пакетом. Удобнее оформлять плагин как питон-пакет. В этом случае каталог с кодом плагина можно легко превратить в bzr-ветку и использовать эту ветку для ведения разработки. Также кроме собственно кода плагина в такой ветке можно спокойно разместить тесты, дополнительные документы (такие как README), скрипт установки setup.py и любые дополнительные ресурсы. Дополнительным удобством такой организации является то, что любой желающий может просто поместить локальную копию ветки с вашим плагином в каталог ~/.bazaar/plugins и тем самым не только подключить плагин, но и иметь возможность легко обновлять код плагина командой bzr pull.
Совместимость с автономной версией bzr.exe для Windows
При использовании автономной версии bzr.exe, которая создается при помощи утилиты py2exe, следует помнить об одной важной детали. Автономная версия bzr.exe содержит интерпретатор Python и большую часть (но не всю!) стандартной библиотеки Python внутри. В дополнение к стандартной библиотеке внутри bzr.exe содержатся библиотеки, необходимые для полноценной работы bzr, такие как paramiko, pyCrypto и т.п. Однако, если для работы вашего плагина потребуется какая-то экзотическая библиотека, то возможности "доустановить" ее у пользователя bzr.exe не будет. В таком случае следует предусмотреть возможность импорта дополнительных библиотек из подкаталога внутри вашего плагина. В качестве примера см. плагин QBzr.
Советы по отладке плагина
Проблемы с загрузкой плагина
В случае проблем с загрузкой кода плагина (ошибки при импорте плагина) вы увидите сообщение на экране:
Unable to load plugin 'foo' from '...'Полный traceback для ошибки записывается в лог-файл .bzr.log. Точное расположение лог-файла можно узнать из вывода команды bzr version (см. строку Bazaar log file).
Отладочная печать
При отладке нетривиальных алгоритмов вам поможет отладочная печать. Вы конечно можете воспользоваться оператором print, но для конечных пользователей это будет создавать ненужный шум и мусор на экране. Поэтому целесообразнее производить отладочную печать в лог-файл .bzr.log. Для этого используйте функцию mutter из модуля bzrlib/trace.py:
import trace
trace.mutter('My debug print')
Для логирования bzr использует стандартную библиотеку logging.Пошаговая отладка
В особо трудных случаях вы можете захотеть использовать отладчик. Для этого можно использовать любой отладчик для Python, как с графическим, так и с консольным интерфейсом. Очень простым вариантом создания "точки останова" в нужном месте с последующим вызовом стандартного отладчика pdb является использование следующего кода:
import pdb; pdb.set_trace()
Публикация плагинов
Чаще всего плагины разрабатывают в отдельных ветках и публикуют их как обычные bzr-ветки. Для публикации bzr-плагинов удобно использовать сайт Launchpad.net. При регистрации нового проекта для bzr-плагина рекомендуется использовать приставку "bzr-", например bzr-email, bzr-svn. Краткое описание вашего плагина и ссылку на страницу с кодом плагина желательно добавить на соответствующую страничку wiki: http://bazaar-vcs.org/BzrPlugins.