пятница, 13 января 2012 г.

Прощай исключение NotYet

Рано или поздно наступает такой момент, когда уже нет возможности мириться с тем или иным косяком (фичей) и ты берёшь в руки чужие исходники и ковыряешь их до посинения. Вот так и у меня случилось с пакетом zope.intid. Меня в конец задолбало исключение NotYet вызываемое по его вине и я просто взял и сделал ему инъекцию стероидов.

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

Вот что я сделал с zope.intid:
  • добавил маркер IIntIdsDisabled - объекты с этим интерфейсом игнорируются утилитой;
  • сделал отложенную индексацию объектов, которые вызвали исключение NotYet.
Реализация второго пункта основана на так называемых слабых ссылках. Используя weakref.WeakKeyDictionary и weakref.WeakSet я создал хранилище ссылок на объекты, которые вызвали исключение NotYet и контейнеры в которые эти объекты добавлялись. Следовательно в тот момент времени, когда эти самые контейнеры будут добавлены в ZODB я могу получить все отложенные объекты и добавить их в индекс утилиты IIntIds.

Благодаря использования слабых ссылок решилась возможная проблема с утечкой памяти - ссылки из хранилища будут автоматически удаленны питоном в случае если объекты, на которые они ссылаются, будут удаленны (т.е. на них не будет ни одной жесткой ссылки).

После того как я завершил работу у меня возникло недоумение - почему за столько лет существования этой утилиты никто не сделал то же самое?

Я отправил в рассылку zopd-dev запрос на добавление моих изменений в основную ветку - надеюсь что хоть кто-нибудь на него откликнется. А пока что мой форк пакета zope.intid можно взять тут.

PS: более подробно про исключение NotYet и возможные способы борьбы с ним при использовании оригинального zope.intid я писал в заметке "Что такое исключение NotYet и с чем его едят".

Комментариев нет:

Отправить комментарий