Source 1.13. Новая версия плагина для OutWiker с исправлением интересной ошибки

Source 1.13. Новая версия плагина для OutWiker с исправлением интересной ошибки

Сегодня выложил новую версию плагина Source для OutWiker, который позволяет раскрашивать тексты программ на викистранице. В этой версии была исправлена давняя проблема, которая могла проявляться под Linux в случае, если у вас в системе была установлена библиотека pygments, которая также входит в состав плагина. Ошибка проявлялась в том, что в этом случае из плагина пропадала поддержка синтаксиса языка 1С, могла ли эта ошибка привести к более серьезным проблемам в случае наличия в системе очень старой версии pygments — вопрос открытый.

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

Итак, чтобы пользователь не заботился о зависимостях плагина, в него уже включена библиотека pygments, которая выполняет всю работу по раскраске кода и созданию HTML. С точки зрения программирования, проблема заключалась в том, что при наличии в системе глобально установленной библиотеки pygments, использовалась именно она, а не та версия, которая прилагается к плагину. А в официальной поставке библиотеки pygments нет поддержки языка 1С.

Чтобы плагин мог импортировать pygments, в начало списка sys.path добавляется путь до плагина Source. Эта переменная инициализируется вначале путями, перечисленными в переменной окружения PYTHONPATH и некоторыми другими путями, где Python будет искать модули при их импорте. Подробности кода здесь не важны, поэтому условно обозначим эту операцию такой строкой:

sys.path.insert(0, 'path_to_source_plugin')

Плагин Source состоит из нескольких модулей *.py. Один из них главный, который инициализирует плагин, а остальные вспомогательные, выполняющую какую-то свою работу, в том числе и по раскраске кода. Поскольку программа (OutWiker) не знает заранее, в каком модуле находится главный класс плагина, она последовательно пытается импортировать все модули, пока не найдет нужный (главный модуль плагина). Если импорт очередного модуля не удается, то ничего страшного не происходит, программа просто переходит к следующему модулю.

Вызов sys.path.insert(0, ‘path_to_source_plugin’) происходит после удачного обнаружения главного модуля плагина.

Один из таких вспомогательных модулей импортирует pygments, и дальше возможны два пути.

Первый путь. Если у нас в системе не установлен pygments, то импорт вспомогательного модуля (в процессе поиска главного модуля плагина), который пытается импортировать pygments, просто проваливается, и основная программа переходит к следующему модулю. Затем будет найден главный модуль плагина, он опять попытается импортировать вспомогательный модуль, тот опять попытается импортировать pygments, уже удачно (т.к. к этому времени будет вызван sys.path.insert(0, ‘path_to_source_plugin’)). Все будет работать как положено.

Второй путь. Если же в системе установлен pygments глобально, то происходит почти то же самое, только вспомогательный модуль удачно импортирует pygments из site-packages, но поскольку главная программа все-равно понимает, что это не главный модуль плагина, то она продолжает искать главный модуль плагина дальше, игнорируя вспомогательный модуль. И когда главный модуль найден, он опять импортирует вспомогательный, а тот уже импортировал pygments, поэтому второй раз его не импортирует, хотя к этому времени был изменен sys.path, и используется pygments, установленный в системе.

Проблема решилась переносом импорта pygments внутрь методов, где он непосредственно нужен.

Все-таки красивая была ошибка!

PS. Вы можете подписаться на новости сайта через RSS, Группу Вконтакте или Канал в Telegram.

Пожалуйста, оцените запись

УжасноПлохоТак себеХорошоОтлично (Количество голосов: 2, средняя оценка: 5,00)
Загрузка...

Leave a comment

Subscribe without commenting