Выбрать главу

Такая тактика выглядела бесперспективной. Даже если не принимать во внимание объем необходимой дублирующей работы, очень трудно быть уверенным в том, что два синтаксических анализатора, написанных на двух различных языках, допускают использование одной и той же грамматики. Обеспечить в дальнейшем их синхронизацию по мере развития конфигурационного языка будет чрезвычайно сложно. Данный подход нарушал бы правило SPOT, описанное в главе 4.

На какое-то время автор был поставлен в тупик данной проблемой. Разрешило ее интуитивное понимание того, что программа fetchmailconf может использовать собственный синтаксический анализатор fetchmail в качестве фильтра. В результате в fetchmail был добавлен параметр --configdump, который позволял бы анализировать файл .fetchmailrc и отправлять результаты на стандартный вывод в формате Python-инициализатора. Для приведенного выше файла результаты выглядели бы приблизительно так, как показано в примере 9.2 (для экономии места некоторые данные, не связанные с примером, опущены).

Основное препятствие было преодолено. Интерпретатор Python мог затем оценить вывод fetchmail --configdump и прочесть доступную для fetchmailconf конфигурацию как значение переменой "fetchmail".

Однако описанное препятствие было не последним. Было действительно необходимо не только предоставить fetchmail существующую конфигурацию, но превратить ее в связанное дерево действующих объектов. В данном дереве было бы 3 вида объектов: Configuration (объект верхнего уровня, представляющий всю конфигурацию), Site (представляющий один из серверов для опроса) и User (представляющий пользовательские данные, связанные с узлом). Файл в примере описывает 3 объекта Site, каждый из которых связан с одним пользовательским объектом.

Данные 3 класса объектов уже существовали в fetchmailconf. Каждый из них имел метод, который заставлял его выводить на экран GUI-панель редактирования для модификации своего экземпляра данных. Последняя проблема сводилась к некоторому преобразованию статических данных в Python-инициализаторе в действующие объекты.

Пример 9.2. Дамп Python-структуры для конфигурации fetchmail

fetchmailrc = {

 'poll_interval':300,

 "logfile":None,

 "postmaster":"esr",

 'bouncemail':TRUE,

 "properties":None,

 'invisible':FALSE,

 'syslog' :FALSE,

 # List of server entries begins here

 # (Ниже начинается список серверов)

 'servers': [

   # Entry for site `imap.ccil.org' begins:

   # (Начало записи для узла imap.ccil.org:)

   {

    "pollname":"imap.ccil.org",

    'active':TRUE,

    "via":None,

    "protocol":"IMAP",

    'port':0,

    'timeout':300,

    'dns':FALSE,

    "aka":["snark.thyrsus.com","locke.ccil.org","ccil.org"],

    'users': [

     {

      "remote":"esr",

      "password":"masked_one",

      'localnames':["esr"],

      'fetchall':TRUE,

      'keep':FALSE,

      'flush':FALSE,

      "mda":None,

      'limit':0,

      'warnings':3600,

     }

    ' ]

   }

  '

  # Entry for site `imap.netaxs.com' begins:

  # (Начало записи для узла imap.netaxs.com:)

  {

   "pollname":"imap.netaxs.com",

   'active':TRUE,

   "via":None,

   "protocol":"IMAP",

   'port':0,

   'timeout':300,

   'dns':TRUE,

   "aka":None,

   'users': [

    {

     "remote":"esr",

     "password":"masked_two",

     'localnames':["esr"],

     'fetchall':FALSE,

     'keep':FALSE,

     'flush':FALSE,

     "mda":None,

     'limit':0,

     'warnings':3600,

    }

   ' ]

  }

  '

 ]

}

Рассматривалась идея написания связующего уровня, который имел бы явную информацию о структуре всех 3 классов и использовал бы данную информацию для просмотра инициализатора при создании соответствующих объектов. Однако данная идея была отклонена, поскольку существовала вероятность добавления со временем новых членов класса, по мере создания новых функций в конфигурационном языке. Если бы код создания объектов был написан таким очевидным путем, то он также был бы хрупким и склонным к рассинхронизации при изменении определения классов либо структуры инициализатора, выводимой с помощью генератора отчетов --configdump. Подобный подход приводит к бесконечному появлению ошибок.