Основное препятствие было преодолено. Интерпретатор 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. Подобный подход приводит к бесконечному появлению ошибок.

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

Программисты, работающие с Lisp и Java, называют данную методику интроспекцией (introspection). В некоторых других объектно-ориентированных языках она называется программированием метаклассов (metaclass hacking) и, как правило, считается "черной магией", понятной только "посвященным". В большинстве объектно- ориентированных языков данная методика не поддерживается вообще, а в тех языках, где она поддерживается (среди них Perl и Java), она часто сложна и ненадежна. Однако в языке Python средства интроспекции и программирования метаклассов исключительно доступны.

В примере 9.3 приведен фрагмент кода приблизительно со строки 1895 в версии 1.43.

Пример 9.3. Код метакласса copy_instance

def copy_instance(toclass, fromdict):

Перейти на страницу:

Все книги серии Программирование для профессионалов

Похожие книги