関数その他のセットが含まれているファイル。
Strawberry Perl を 5.10.0 系から 5.12.1 系に入れ替えたので再度 CPAN モジュールを使って必要な Perl モジュールをインストールしようとしたが、前のバージョンの時と同様
"Couldn't move...
と出てエラーで止まってしまった。今回は解決しておこうと調べたところ Norton Internet Security のせいらしい。ロック関係だとは思っていたが、NIS が掴んでいたか。一時的に Auto-Protect を無効にしたらすんなり通るようになった。
@bulkneets 氏からの言及経由 @mikio1978 氏によると FILE_SHARE_DELETEとかの共有フラグを立てないでオープンしてしまっているからのようだ。
ちょっとしたものをのぞいて、Perl プログラムはアプリケーション部分も App 的 Perl モジュール(.pm)に入れて、実行するスクリプトファイル (.pl) では use して new して run するだけにしている。
#!/usr/bin/perl use warnings; use strict; use MyApp; exit MyApp->new->run;
@ARGV の処理は new から呼ばれているプライベートメソッドの中で local @ARGV してから、Getopt::Long::GetOptions あたりで解析処理をしている。
でテストスクリプトではこの MyApp を use_ok して local @ARGV = qw(引数組み合わせパターン...) した後に new を呼んだ結果を検査するようにしていた。
そんなところ今回「.pm の中で @ARGV いじるのやっぱり気持ち悪くない?」っていう意見をもらった。気持ちはわかる。ただ
MyApp->new(@ARGV)->run;
のように .pl 側で受け取ったものを解析すれば?」いいかというと、直接 @ARGV を使わない Getopt::Long::GetOptionsFromArray は 2.36 からしかなくて、古いバージョン の Getopt::Long でも動くようにすると結局 local @ARGV になってしまうのである。
また「@ARGV の解析は .pm の方には入れたくない」っていう意見もあったので、今回はそれらのコードは .pl 側に追い出すことにした。
そうすると次の課題は .pl にある @ARGV の解析処理のテストはどう書けばいいかなと。.pl ファイルを require したらスクリプトが走っちゃうし。試行錯誤していたらマスタリング Perl で紹介されている caller(0) を使う方法を教えてもらった。
スクリプトファイル(.pl) #!/usr/bin/perl package App; # スクリプトの実行開始エントリ sub main { # ここに実行したい処理呼び出しを書く。 } main() unless caller(0);
こうするとこのスクリプトファイルを直接実行した場合は main サブルーチンが実行され、他から require された場合は main は実行されないというようにすることができる。前者の場合は caller(0) は undef を返し、後者は 'main' (あるいその他のパッケージ名)が返されることを利用している。
これでテストファイルの中でこのファイルを require_ok できるようになるので、あとは各サブルーチンのテストを書けばよい。
それから Pod::Usage を使っているんだけれど、テストでは Pod::Usage::pod2usage で exit されてしまうと困るので exit が何もしないようにしておく。テストスクリプトでは以下のようにする。
BEGIN { *CORE::GLOBAL::exit = sub {}; require_ok('script/myscript.pl'); }
これで myscript.pl のテスト中に pod2usage が exit を呼んでもスルーさせられる。 ただし本番では exit させたい pod2usage がある場合は、その後に制御が流れていっても問題がおきないようにプログラムを書いておく必要があるので注意。
それから pod2usage で期待するメッセージが STDERR に吐かれているかをテストするには STDERR をオープンしなおせばよい。
{ my $message; local *STDERR; open STDERR, '>', \$message or die $!; # ここで pod2usage がメッセージを出すことが期待されるテストを実行。 like($message, qr/expected message/); }
以上、スクリプトのテストについての何点かのまとめ。
いよいよ YAPC::Asia Tokyo 2013 スタート!
今回は席に電源があるので安心してノート PC・スマートフォンを使えるので嬉しい。 Wi-Fi がつながっても DHCP で アドレスがもらえなくて通信できなかったりすることがあるのでちょっと注意。いったいどれだけ接続してるんでしょうね。これだけ geek の集まる会場で Wi-Fi 環境整えるの相当ノウハウがいるのだろうなあ。
Perl の今後の機能追加・変更 (experimental features) についての話。まだまだ Perl 5 は Perl 5 のまま変わっていくと。便利になったり直観に反するものが減ったりとか良くなっていく。シンタックス/セマンティクスがさらに肥大化していくのは初学者にはちょっと厳しくなるのな。
この話につきものの互換性の話もあった。去年のスピーカーは互換性を大事にするという話だったけれど、今回は互換性を恐れずに改良していくというニュアンスに感じられた (聞き間違えでなければ)。個人的には Perl は古いスクリプトがそのまま動くのがとてもいいと思っているので、そのあたりも引き続き大事にされると嬉しいな。
LINE株式会社では mod_perl から PSGI/Plack にほぼ移行済みとのこと。Starlet を使っている。
今回はリバースプロキシとアプリケーションサーバ間の大量のリクエストを捌くために Monoceros を開発しているというお話。あと PSGI/Plack の基本概念の解説もあって嬉しい。 Perl で書かれた HTTP サーバがハイパフォーマンス出せるなんて、昔は自分は考えもしなかった。
PSGI/Plack のサーバを書く人必見な、中身の濃いトークでした。
RTB システムに Riak を使ってみたというトーク。良い Perl モジュールが無いので作ったとのこと。
DeNA の Perl エンジニア初心者研修プロジェクトについて。Class::Data::Inheritable がコードリーディング教材とし良いらしい。
高速化されたプロトコルの話かなと思っていたけれど、ドヤリングから暗号化という導入で引き込んでいく手慣れたトーク。本格的に使われ始めるのは来年以降?
たまにお名前が話題にあがることのあった @bonar 氏と初対面のご挨拶をさせていただきました。今後ともよろしくお願いします。
社内の Perl 技術動向について談議。最近は解き放たれてきたねとか。
Perl 6 の話など。
Google 翻訳を使ったキュートなスライド (ほとんど聞いてなかった)。
@kazuho 氏の prove のトークで始まって、最後日本人による中国語 (のような違うような) でのトークでシメ。
乾杯。
多目的教室3は常に人気で入ろうとしたけど1度も入れなかった。部屋遠しが近いので人気なトークがあるとさっと集るのかもね。
そういえば今年の T シャツ、背中に pixiv って大きく書かれていて着用できないものだということに気がついた。残念。 ピクシブが T シャツスポンサーだからなのかな。スポンサーのおかげで運営ができたりチケット代が抑えられたりできていると思うので素晴しいと思うのだけれど T シャツについては有無でチケット代が違うので、大きく広告が載りますよってチケット発売時に明記してくれるといいと思う (自分は先行販売で買ったので T シャツの有無は選べないから関係なかったけど)。
TLS と認証が必要な SMTP サーバ経由でメールを送信する以前書いたスクリプトをちょっと整理した。標準入力からメッセージ本文を受けとって送信できるように機能を切り出し。
メールでコンテンツを投稿できるサービスにメールを投げる時用。
標準入力で受け取った本文を Email::MIME でメールの形式に変換して、Email::Sender::Simple を使って送信。transpot として Email::Sender::Transport::SMTP::TLS を使う。なお、今 Email::Sender::Transport::SMTP::TLS の Pod ドキュメントをみたら今後は Email::Sender::Transport::SMTPS の方がお薦めと書いてあったのでその方が良いのかも。
#!/usr/bin/perl use warnings; use strict; use utf8; use open IN => ':utf8'; use open ':std'; use Email::MIME; use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP::TLS; eval { my $message; { local $/ = undef; $message = <>; } my $subject = "sendXXX: $message"; $subject = substr($subject, 0, 32 - 3) . '...' if length($subject) > 32; my $new_mail = Email::MIME->create( header_str => [ From => 'me@example.com', To => 'post@example.com', Cc => 'me@example.com', Subject => $subject, ], attributes => { content_type => 'text/plain', charset => 'UTF-8', encoding => '8bit', }, body_str => $message ); sendmail( $new_mail, { from => 'me@example.com', transport => Email::Sender::Transport::SMTP::TLS->new( { host => 'smtp@example.com', port => 587, username => 'myusername', password => 'mypassword' } ) } ); }; if ($@) { open my $file, '>>', '/home/me/var/log/sendXXX/error.log' or die $!; print $file $@, "\n"; close $file; exit 1; } exit 0;
[ Perl モジュール ]
Git でファイル中の特定の範囲の変更履歴を見る -L オプションで、その範囲を正規表現で指定できる。例えば Perl モジュールだと
git log -L '/sub func_name/',/^}/:lib/Foo/Bar.pm
で lib/Foo/Bar.pm の中の func_name サブルーチン(/関数/メソッド)の変更履歴(sub func_name のある行から、行頭が } の行までの変更履歴)を出力できる。
IRC チャネルに常駐してメッセージの内容を受けて何かをする IRC bot を Perl の AnyEvent::IRC::Client を使って作ってみた。大枠は以下の感じで意外とサクッと書けた。
#!/bin/env perl use warnings; use strict; use utf8; use Encode; use AnyEvent; use AnyEvent::IRC::Client; my $irc_server = 'irc.example.com'; my $irc_port = 6667; my $irc_password = 'password'; my @irc_channels = ("#sandbox"); my $irc_nick = 'ae-bot'; my $c = AnyEvent->condvar; my $irc = AnyEvent::IRC::Client->new; $irc->reg_cb( publicmsg => sub { my ($irc, $channel, $message) = @_; my $message_text = decode_utf8($message->{params}->[1]); my ($mode, $nick) = $irc->split_nick_mode($message->{prefix}); # 他の webhook たたいたりもろもろする。 } ); $irc->connect($irc_server, $irc_port, {nick => $irc_nick, password => $irc_password}); $irc->send_srv("JOIN", $_) foreach @irc_channels; $c->recv;
最近ノートやちょっとしたドキュメントは Markdown で書いて、Plack::App::Directory::Markdown (記事) (に手を入れて grep 検索や recent リストを表示できるようにした) Markdown ビューアで参照したり、関係者に見せたりしている。
重宝しているんだけれど、内部で使っている Text::Markdown Perl モジュールは、テーブルや GitHub Flavored Markdown にある fenced code blocks (``` で挟むやつ) が使えないのでちょっと不便になってきた。
Text::Markdown::Discount Perl モジュールはこの辺の拡張が使えるので、こちらに切り替えることにした。
このモジュールは discount というC言語書かれた Marrkdown 処理コードを使うもので、Text-Markdown-Discount 内に同梱されている。
そのままインストールすると fenced code blocks が有効になっていないので以下のようにしてインストールする。
$ tar zxvf Text-Markdown-Discount-0.11.tar.gz $ cd Text-Markdown-Discount-0.11 ここで Makefile.PL 中の qq{( cd $extdir; CC='cc -fPIC' sh configure.sh; make )\n} を qq{( cd $extdir; CC='cc -fPIC' sh configure.sh --with-fenced-code; make )\n} に変更する。 $ cpanm .
で Text::Markdown::markdown() のかわりに Text::Markdown::Discount::markdown() を使うようにすれば OK。
なお自動リンクをしたい時には
my $html = Text::Markdown::Discount::markdown($markdown_text, Text::Markdown::Discount::MKD_AUTOLINK);
のようにオプションを指定してあげる。
昨日の前夜祭から一夜明けての YAPC::Asia Tokyo 2014 1日目。昨年に引き続き慶應義塾大学 日吉キャンパス開催なのでなんとなく勝手がわかってちょっと気楽。去年はなんか多目的教室に入りそびれたので、今回は早めに移動とかしてそちらも回ってみた。
電源の取れる藤原洋記念ホールがなんだかんだいって居心地が良かったりはするんだけれどね。
今日は Go 使ってみようかなと思ったのが収穫。会場でとりあえず golang Debian パッケージをインストールして hello.go ぐらいはしてみた。goroutine 以外は思っていたより普通の言語……なのかな?
お昼は @syamata 氏と @bornite 氏と日吉天神でラーメン。去年と同じ店だった。と思ったら去年は同じ場所で「らーめん 元山亭」という店だった。日吉天神は去年10月7日オープンらしい。 @syamata 氏が最近 Facebook で Yelp のフィード流しているのでモチベーションとか聞いてみたら「アーリーアダプターとして、まだデータにないお店やレビューを登録していくのが楽しい」とのこと。あーわかる。
インフラエンジニアのメンタル的な面に視点を当てたトーク。
Go 使ってみたくなった。
テストフレームワーク関連はできるだけ枯れて安定したものがいいなと思う(テストフレームワークの不具合とか仕様変更まで追いかけ続けなくていいように)。便利さとのトレードオフ。
わりに泥臭い世界なのではと思ったら、やはり泥臭い感じだった(実装的に)。
C スタイル for だって goto だって適材適所なので使った方が良い場面だってあるので、そういうのはきちんと説明できるといいんじゃないかと思う(lint がそこまで判別できたら凄いけど)。
フルフルの汎用モジュール使わないで、軽くて速い機能を削った専用モジュールを作って使うのもいいよという話。
経営的な視点まで入った技術選択の考え方の概論トーク。
MySQL のインデックスを Perl データ構造で擬似的に説明。
フォントかわいいけどコード部分とかちょっと見辛かった。
ビギナー向け。
ハッシュタグ #yapcramen
(画像は http://yapcasia.org/2014/ より)
Plack::App::Directory::Markdown をベースにちょっと手を入れた Markdown ビューアを使っている(記事)んだけれど、閲覧要認証なシチュエーションが出てきた。
自分のみ閲覧のものは builder で Plack::Middleware::Auth::Digest を enable にして Digest 認証をかけ、htdigest コマンドでパスワード管理とかで済ませているのだけれど、複数人に閲覧してもらうのにこれは嫌だ。人のパスワード管理はしたくない。
OAuth で Google アカウントとかの認証を使うというのもあるけれどキーとか面倒くさいので、せっかくだし mixi OpenID を使うことにした。Perl モジュールは Net::OpenID::Consumer::Lite を使用。
とりあえずやっつけで以下のような感じ。いきなり mixi OpenID 認証させるしエラー・キャンセル処理もほとんどないし、call の中にネジこんだりしてあるので、まだまだダメダメだけれどとりあえず認証はできた。後で整理する。
$app = builder { enable 'Session', store => 'File'; $app; };
my $session = $env->{'psgix.session'}; my $request = Plack::Request->new($env); unless ($session->{openid}) { unless ($request->parameters->{'openid.mode'}) { my $check_url = Net::OpenID::Consumer::Lite->check_url( 'https://mixi.jp/openid_server.pl', $request->uri); return [302, ['Location' => $check_url], []]; } return Net::OpenID::Consumer::Lite->handle_server_response( $request->parameters => ( not_openid => sub { return [503, [], []]; }, setup_required => sub { my $setup_url = shift; return [302, ['Location' => $setup_url], []]; }, cancelled => sub { return [403, [], []]; }, verified => sub { my $vident = shift; my $identity = $vident->{identity}; # %member に閲覧 OK の OpenID を入れてある。 if (exists $member{$identity}) { $session->{openid} = $identity; return [302, ['Location' => $vident->{return_to}], []]; } else { return [403, [], []]; } }, error => sub { my $err = shift; return [503, [], []]; }, ) ); } # 以下は認証済みの場合の処理を書く。
[ Naney と mixi ]
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。