![]() | Ned Batchelder : Blog | Code | Text | Site Cog » Home : Code : Cog |
Created 10 November 2004, last updated 24 May 2008 (Оригинал текста на английском языке находится здесь. Перевод на русский язык: Александр Бельченко, страница обновлена 19 мая 2008.) Cog — это инструмент для генерации исходных текстов программ. Он позволяет вам использовать небольшие фрагменты программ на языке Python в качестве генераторов в вашем исходном коде. Такие генераторы могут создавать любой код, который вам нужен. Разделы:
Что делает эта утилита?Cog преобразует файлы достаточно простым способом: он находит куски Python-кода, встроенные в файл, выполняет этот Python код, и затем вставляет результат работы в оригинальный файл. Файл может содержать любой текст вокруг участков Python-кода. Обычно это исходный код какой-нибудь программы. Например, если пропустить следующий файл через Cog: // This is my C++ file. в результате получим нечто похожее на это: // This is my C++ file. Строки, которые содержат тройные квадратные скобки, являются разделительными (или маркерными). Строки между [[[cog и ]]] содержат код Python-генератора. Строки между ]]] и [[[end]]] содержат результат работы генератора. Когда Cog начинает работать, он удаляет последний сгенерированный результат, затем выполняет код Python-генератора и записывает новый результат работы назад в файл. Все строки текста, находящиеся за пределами специальных маркеров, остаются нетронутыми. Строки с Cog-маркерами могут содержать любой текст в дополнение к тройным квадратным скобкам. Это позволяет спрятать код Python-генератора в исходном файле. В вышеприведенном примере весь кусок Python-кода — это C++ комментарий. Таким образом Python-код может быть оставлен в тексте, в то время как файл будет восприниматься как обычный C++ код. ДизайнCog спроектирован так, чтобы быть простым и удобным инструментом. Он записывает результат своей работы назад в исходный файл, сохраняя при этом встроенный код генератора. Это означает, что Cog может быть запущен любое число раз для одного и того же файла. Вместо того чтобы использовать отдельный исходный файл с кодом генератора и отдельный выходной файл, в типичном случае Cog в процессе работы использует только один файл, который является и генератором и выходным файлом. Поскольку маркерные строки адаптированы под синтаксис любого языка, то маркеры могут скрыть Python-код генератора внутри исходного файла. Это означает, что Cog-файлы могут быть включены в базу контроля версий, и при этом не нужно беспокоиться о том, чтобы хранить отдельно исходный файл с генератором и результирующий выходной файл. Это также означает, что вам не нужно менять сложившуюся методику компиляции-сборки проекта и т.д. Я экспериментировал с различными инструментами, которые генерируют некоторый код по шаблону. И я замечал, что мне постоянно приходиться бороться с появлением нежелательных символов пробелов в генерируемом выходном файле, и что я мысленно преобразовывал некоторый воображаемый Python-код в его эквивалент в виде шаблона. Преимущества систем-шаблонизаторов (в которых большинство кода может быть задано литерально) исчезают, как только задача генерации кода становится все более и более сложной, и как только в процессе генерации требуется все больше логики. Cog позволяет вам использовать всю силу языка Python для генерации кода, без использования шаблонов — простых, но в то же время имеющих ограниченные возможности, инструментов. УстановкаДля работы Cog требуется Python 2.3 или более поздней версии. Чтобы воспользоваться дополнительными возможностями, вам могут понадобиться следующие пакеты: Cog устанавливается при помощи стандартного установочного скрипта (Python distutils).
По окончании установки в подкаталоге scripts для Python-скриптов должен появиться скрипт cog.py. ЛицензияCog распространяется согласно MIT лицензии. Используйте Cog, чтобы сделать этот мир чуточку лучше. Как писать исходные файлыИсходные файлы, предназначенные для обработки утилитой Cog, — это чаще всего обычные текстовые файлы, которые должны оставаться нетронутыми. Код Python-генератора в вашем исходном файле — это стандартный Python-код. Допускаются любые вариации использования Python для генерации необходимого текста в вашем файле. Каждый участок Python-кода (между строками [[[cog и ]]]) называется генератором, все генераторы будут выполнены по очереди. Область вывода для каждого генератора (т.е. строки между ]]] и [[[end]]]) очищается, и на это место вставляется новый результат работы Python-генератора. Формат маркерных строк не имеет существенного значения, что позволяет адаптировать их к любому типу исходных файлов. Если строка содержит последовательности специальных символов, то вся строка интерпретируется как маркер. Например, любая из этих строк отмечает начало выполняемого Python-кода: //[[[cog Cog также может использоваться в языках, в которых отсутствуют многострочные комментарии. Если все маркерные строки содержат некоторый текст перед тройной скобкой, и все строки кода генератора также содержат тот же текст в качестве префикса, то этот префикс удаляется перед выполнением кода Python-генератора. Например, имеется следующий SQL-файл: --[[[cog который в результате работы Cog станет таким: --[[[cog Кроме того, для однострочных генераторов может быть использована компактная форма. Маркер начала кода, и маркер конца кода могут находиться на одной строке, и весь текст между этими маркерами будет рассматриваться как одиночная строка Python-кода: // blah blah Эта форма записи также может использоваться для простого импорта модуля. Исполняемые операторы верхнего уровня в таком модуле могут производить действия по генерации кода. Если в одном и том же файле присутствует несколько вставок с генераторами, то они будут исполняться с использованием единого словаря имен. Таким образом, их поведение будет аналогичным тому, как если бы они все были в одном Python-модуле. Cog старается соблюдать ваши правила по использованию пробелов. Ваш Python-код может иметь блочный отступ от левого края в соответствии с окружающим его текстом. При этом Cog также будет добавлять необходимые отступы в своем выводе, чтобы соблюсти эту закономерность. Весь вывод генератора собирается в единый блок текста, общий отступ для всех строк удаляется и затем блок текста выравнивается отступами согласно отступу самого cog-генератора. Это значит, что самый крайний слева непробельный символ в вашем выводе будет иметь такой же отступ, как и маркер начала кода cog-генератора. Остальные строки в вашем выводе будут сохранять свои отступы относительно друг друга. Модуль CogМодуль Cog предоставляет вам для использования функции, при помощи которых можно выводить желаемые строки в ваш файл. Ниже приведено описание этих функций.
cog.out(""" В дистрибутив Cog включен модуль handyxml, поскольку я использую файлы данных в формате XML в своих собственных задачах генерации кода. Запуск CogЗапуск Cog выполняется из командной строки, аргументы передаются стандартным образом. cog - генерация исходных текстов при помощи встроенного Python-кода. Указанные в командной строке имена файлов используются в качестве входных файлов и обрабатываются Cog. Имена файлов также могут быть переданы в виде списка в текстовом файле, который передается как аргумент с префиксом @: $ cog @files_to_cog.txt Эти @-файлы могут быть вложенными, и каждая строка может содержать опции командной строки вместе с именем файла для обработки. Например, вы можете создать файл cogfiles.txt:
и затем запустить Cog следующим образом: cog -s " //**cogged**" @cogfiles.txt В этом случае Cog будет обрабатывать 4 файла, используя синтаксис C++ для маркирования генерируемых строк во всех C++ файлах, SQL синтаксис для .sql файла, и вообще без маркеров в файле readme.txt. В качестве другого примера рассмотрим файл cogfiles2.txt:
Если запустить Cog следующей командой: cog -D version=3.4.1 @cogfiles2.txt То Cog обработает файл template.h дважды, создав два файла data1.h и data2.h. Для каждой обработки будет определена переменная version со значением "3.4.1", но для первого запуска переменная thefile будет равна "data1.xml", а для второго запуска переменная thefile будет равна "data2.xml". Перезапись файловФлаг -r указывает Cog о необходимости записи вывода назад во входной файл. Если входной файл защищен от записи (например, если он не был извлечен из системы контроля версий для редактирования), то при помощи флага -w можно указать команду, которая выполнит необходимые действия для разрешения записи в файл: $ cog -r -w "p4 edit %s" @files_to_cog.txt Установка глобальных переменныхЗначения глобальных переменных могут быть установлены в командной строке при помощи ключа -D. Например, если запустить Cog следующим образом: cog -D thefile=fooey.xml mycode.txt то Cog начнет обработку файла mycode.txt, но предварительно определит глобальную переменную с именем thefile и присвоит ей значение "fooey.xml". Эта переменная затем может быть использована в ваших генераторах кода. Вы можете указывать ключ -D многократно в командной строке, определяя несколько глобальных переменных. Значение всегда интерпретируется как Python-строка, для упрощения проблем с обработкой кавычек. Это означает что: cog -D NUM_TO_DO=12 определит переменную NUM_TO_DO не как целое значение 12, а как строку "12". Эти два значения различаются по типу и не эквиваленты по значению в языке Python. Используйте код int(NUM_TO_DO) для приведения строки к числовому значению. Добавление контрольной суммы к генерируемому текстуЕсли Cog запущен с флагом -c, то генерируемый текст будет сопровождаться указанием его контрольной суммы: --[[[cog Если сгенерированный код будет отредактирован разработчиком, которого не проинформировали о назначении кодогенератора, то при следующем запуске Cog обнаружит, что контрольная сумма не сошлась, и прекратит обработку, чтобы избежать перезаписывания отредактированного участка кода. Добавление суффикса к генерируемым строкамДля того, чтобы было проще отличать сгенерированные строки когда вы проводите поиск в файлах при помощи grep, ключ командной строки -s позволяет указать суффикс, который будет добавляться к каждой непустой строке, генерируемой Cog. Например, имеется следующий входной файл (mycode.txt):
Запуская Cog такой командой: cog -s " //(generated)" mycode.txt получим такой выходной файл: [[[cog РазноеФлаг -x указывает утилите Cog удалить весь ранее сгенерированный текст без запуска кодогенераторов. Этот флаг позволяет вам удалить весь автоматически сгенерированный код из исходного файла. Флаг -d указывает утилите Cog удалить все генераторы из выходного файла. Этот флаг позволяет вам генерировать код в общедоступных файлах, но при этом вы можете не показывать генератор своим клиентам. Флаг -U заставляет Cog записывать выходные файлы с использованием Unix символа перевода строки (LF) вместо концовок строк, принятых на конкретной платформе. Вы можете использовать этот флаг в ОС Windows для создания выходных файлов в Unix-стиле. Флаг -I добавляет каталог к списку путей, в которых ведется поиск Python-модулей, и в которых ведется поиск файлов для обработки модулем handyxml. Флаг -z позволяет опускать строку с маркером [[[end]]], при этом предполагается, что он находится в конце файла. ИсторияСписок изменений в версиях Cog приведен на отдельной странице. Обратная связьМне будет приятно услышать о ваших успехах или трудностях при использовании Cog. Оставьте комментарий здесь, или напишите мне небольшое письмо. Пожалуйста, пишите на английском языке. СсылкиИмеется также несколько других воплощений Cog-идей:
Возможно, вы захотите прочитать:
| |
Comments
Add a comment: