Новые мероприятия в 2009 году

Появилась новая информация о мероприятиях, которые пройдут в текущем году.

С 30 октября по 1 ноября в Рио-де-Жанейро пройдет YAPC::Brasil. Замечательный повод побывать в Бразилии 🙂 Правда, сайт мероприятия — только на португальском языке.

5 декабря в Лондоне состоится очередной лондонский Perl-воркшоп. Традиционно лондонский воркшоп не берет плату за вход, но при этом устраивает вечеринку в пабе.

Напомню также, что 21 ноября в Риге пройдет первый балтийский Perl-воркшоп.

XML и ручной ввод

Один из самых неприятных моментов в программировании сайтов, использующих XML, — это обработка кода, пришедшего от визуального редактора.

С одной стороны хочется разрешить коллегам-редакторам не только пользоваться предопределенными действиями, нажимая на кнопки, но и дать возможность ввести нужные HTML-теги, если это необходимо. Но при этом любой некорректный ввод, если его поместить в XML, потенциально способен не только сделать XML невалидным, но в худшем случае сделает неработоспособной и саму страницу с редакторским веб-интерфейсом, лишая возможности исправить ошибку.

Прямолинейное решение — экранировать все угловые скобки, обрамляющие теги, амперсанды и HTML-сущности, а потом обернуть все это в блок CDATA — ненамного лучше полного вырезания тегов, ибо приводит, среди прочего, к тому, что полученный код неудобен для обработки с помощью XSLT. Например, довольно сложно (и даже неоправданно сложно) будет дополнить внешние ссылки классом external:

Читайте об этом на <a href=»http://wikipedia.org/»>Википедии</a>.

Разумеется, возможно решить задачу, привлекая Perl, но чем сильнее разметка превращается в текст, тем сложнее обрабатывать более сложные случаи.

Все, что нужно сделать, — заставить себя один раз написать валидатор и затем им с удовольствием пользоваться.

Я использую примерно такой вариант. Полученный от пользователя код встраивается в итоговоый XML-документ так, словно он был написан участниками комитета W3C в редакторе Altova XML Spy:

my $xmlParser = new XML::LibXML();
$xmlParser->expand_entities(0);
my $contentFragment =
    $xmlParser->parse_xml_chunk(make_well_formed_xml($content));
$contentNode->appendChild($contentFragment);

Функция make_well_formed_xml() выполняет несколько последовательных преобразований, включая правку с помощью libtidy и замену сущностей:

sub make_well_formed_xml {
    my $content = shift;
    utf8::decode($content);
    my $tidy = HTML::Tidy->new({
        'output-xhtml' => 1,
        'doctype' => 'omit',
        'show-body-only' => 1,
        'fix-uri' => 1,
    });
    $content = $tidy->clean($content);
    $content =~ s{<}{<!ENTITY lt>}g;
    $content = XML::Entities::decode('all', $content);
    $content =~ s{<!ENTITY lt>}{<}g;
    $content =~ s{&}{&}g;
    return $content;
}

Грязные места в коде — декодирование UTF-8 и замену открывающей угловой скобки — конечно нужно заменить более аккуратным кодом, но поскольку все теперь локализовано в единой функции, это можно отложить на потом, и такой код будет работать годами 🙂

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

Про Perl на разных языках

Габор Сабо создал на вики сайта Perl Foundation страницу International Perl Resources, где попросил сообщество собрать ссылки на материалы про Perl на разных языках.

В результате за пару дней набралось ссылок на двадцати языках. Русский язык оказался на одном из первых мест по числу ссылок.

Пополнить коллекцию приглашаются все желающие.

Габор Сабо (Gabor Szabo) — активный участник Perl-сообщества, создатель редактора Padre, организатор нескольких мероприятий в Венгрии и Израиле. В 2009 году получил награду White Camel Award.

libapreq2

Как бы ни ругали модуль CGI, я особо никогда не прислушивался к аргументам, потому что пользовался им только тогда, когда учился программированию для веба.

В основном я использовал самописный парсер HTTP-запроса, который проработал почти без изменений больше пяти лет. Парсер умел разбирать все, в том числе и multipart/form-data, хотя и написан он не слишком высокопарно.

Потом, когда пришел UTF-8, потребовался mod_perl, а самописному парсеру стало все труднее справляться с запросами, я заменил его библиотекой libapreq2. Libapreq — это Apache HTTP Server Request Library. Это модуль, который собирается в отдельную библиотеку и подключается к Апачу:

LoadModule apreq_module modules/mod_apreq2.so

Установка весьма простая, однако следует помнить, что для установки сопутствующих Perl-модулей требуется вызывать не ./configure, a perl Makefile.PL:

perl Makefile.PL --with-apache2-apxs=/path/to/apache2/bin/apxs

В каталоге modules появится соответствующие бинарные библиотеки, а Perl получит модули для работы с ней, в частности, Apache2::Request.

Миграция с CGI или любого другого парсера на libapeq2 проходит гладко, поскольку, собственно, и задачи формулируются весьма просто: получить переменную из запроса или прочитать куку.

my $req = new Apache2::Request($this->{'r'});
$p{$_} = $req->param($_) for $req->param();

Так же просто читать куки и еще более просто получать прикрепленные файлы:

my $upload = $req->upload($param);

Итого: если у вас mod_perl, пользуйтесь libapreq.

Free / gratitudo / libero

Тот факт, что Perl был создан лингвистом, не мог не надожить отпечаток и на пользователей языка. Довольно часто разговоры между любителями перла перетекают на обсуждение языков. Не языков программирования, а языков человеческих.

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

Даккар приводит такие примеры:

VMWare Server è *gratuito*. (VMWare Server бесплатный.)

VirtualBox e qemu sono *liberi*. (VirtualBox и qemu свободные.)

К сожалению, читать итальянскую рассылку mongers@lists.perl.it можно только «вживую», веб-архива у нее нет.

Padre

Вчера вышло очередное обновление написанной на перле интегрированной среды Padre.

Сейчас все работает и под Windows, и под Mac OS. Есть и русский перевод (я его обновлю на днях).

А то, что размер дистрибутива 40 МБ, не должно сильно смущать: в комплекте идут все необходимые компоненты, включая сам Strawberry Perl. Надеюсь, что со временем такого избыточного комплекта не потребуется.

Где можно увидеть Тима Банса

Tim Bunce — автор модуля DBI — 12 и 13 октября приезжает в Москву, чтобы выступить на конференции HighLoad++.

На вечер 12 октября (понедельник) в «Инфопространстве» запланирована встреча с Moscow.pm. Начало в 19 часов, вход свободный.

Кроме того, Тима в ближайшее время можно увидеть на пятом итальянском Perl-воркшопе в Пизе 22 и 23 октября.

Один из докладов, с которыми он собирается выступить, — Perl Myths. В рассылках про Perl 6 и Parrot сейчас идет обсуждение о том, чем стоит дополнить существующий материал.

О сложности и простоте

На прошлой неделе мне потребовалось автоматически постить RSS в Твиттер.

Первая мысль была — использовать Plagger. Тем более, что именно эту программу ребята использовали на январском хакмите в Москве.

Plagger — это такой механизм, где с помощью конфигурации (в YAML) формируется цепочка, через которую проходят новости, собираемые из разных источников. Всю обработку ведут отдельные плагины: один забирает RSS, другой фильтрует данные, третий размещает их в Твиттере, отправляет по почте или складывает в XML-файлы. Конфигурация может быть самой замысловатой, а отдельных плагинов больше сотни.

Установка оказалась весьма муторной, заняла часа полтора и скачала пол-спана. К тому же, не очень понятно (а документации — кот наплакал), как не пропускать дубликаты записей и как заставить плагины сохранять результаты в базе данных. Необъятное число необходимых модулей заставило задуматься о том, насколько сложно будет переносить скрипты на другой сервер.

В итоге я расчехлил архивы трехлетней давности и все приложение свелось к последовательному вызову нескольких методов:

my $feeds_ref = FeedCrawl::Register::getFeeds();

foreach my $feed (@$feeds_ref) {
    print $feed->id . ' ' . $feed->uri . "\n";
    $feed->fetch();
    $feed->save();
}

Признак старинной архивной копии — вызов print 🙂

Ну а пост в Твиттер — тривиальная операция. Все сразу заработало, а через несколько часов окончательно вышел из строя жесткий диск на арендованном у «Мастерхоста» сервере, поэтому скрипт переехал жить и работать во Франкфурт.

Far East Perl 2008 — что было до и после

Про Дальневосточный Perl-воркшоп, который прошел год назад во Владивостоке, тоже есть что рассказать помимо собственно перла.

Уже то, что мероприятие прошло на другом конце континента, докуда от Москвы лететь восемь часов (а обратно — девять), само по себе волнующе. Это была моя первая вылазка на Дальний Восток.

Зарегистрировалось около 30 человек, в основном, разумеется, из Владивостока. Приехал и Джонатан Вортингтон. К сожалению, никого не было ни из Хабаровска, ни из Японии (хотя, впрочем, из Японии во Владивосток добраться сложнее, чем из Москвы).

Экскурсионная программа (за которую спасибо Vladivostok.pm — ДимеИлье и Роману) для организаторов и гостей включала, не считая прогулок по городу и чаепитий, поездку к Русскому острову и шашлыки на природе с исследованием подземных ходов.

Русский остров — особый пункт для тех, кто любит Гришковца.

Не менее интересно было спуститься в заброшенные ходы владивостокских фортов.

Видеозаписи всех выступлений на Дальневосточном Perl-воркшопе доступны на yapc.tv.

Perl и Project Euler

Часть задач, опубликованных на сайте Project Euler, удобно решать с помощью перла.

Некоторые задачи — исключительно математические, а некоторые требуют посимвольной обработки чисел или строк.

Например, задача на поиск чисел-палиндромов, то есть чисел вида 78987. С одной стороны, они представимы в виде суммы 7·104 + 8·103 + 9·102 + 8·101 + 7·100, но с другой — это последовательность символов, которые легко преобразовать в массив односимвольных элементов:

my @digits = split //, $number;

В задаче, где предлагается отсыкать максимальное произведение пяти последовательных цифр в числе из 1000 цифр, это число также удобно рассматривать как строку, выделяя ее часть встроенной функцией substr:

$product *= $_ for split //, substr $n, $c, 5;

Кроме того, некоторые задачи подразумевают большие числа — настолько большие, что размера стандартных переменных (например, long long в C++) недостаточно для их представления. Для работы с такими числами в перле удобно воспользоваться модулем Math::BigInt или прагмой bigint, после чего программа, вычисляющая сумму цифр факториала ста, становится тривиальной:

$i = $i->bmul($_) for 2..100;
. . .
$s += $_ for split //, $i;