Test::PAUSE::Permissions

たまに、そう、CPANディストリビューションの割合からすると1%ほどのことではあるのですが、他の人からモジュールを引き継いだときに必要なパーミッションを全部もらえていなかったとか、名前がかぶっているのに気づかなかったとかで、PAUSEの索引に登録してもらえないディストリビューションが生まれてしまうことがあります。

そういう問題を防ぐにはリリース前にPAUSEのパーミッションの確認しておくに限る、というわけで、Test::PAUSE::Permissionsというモジュールをリリースしました。

基本的な使い方は、SYNOPSISに書いてある通り、xt/perms.tのようなテストファイルにこう書いておくだけ。

use strict;
use warnings;
use Test::PAUSE::Permissions;

all_permissions_ok();

リリース時に(環境変数RELEASE_TESTINGを有効にして)このテストを実行すると、ディストリビューション内のpackageを抽出し、CPANからパーミッションの索引をダウンロードしてきて、それぞれのpackageについて、パーミッションの状況を確認します。持ち主が登録されていない(誰もそのpackageを登録したことがない)か、持ち主に自分が含まれていればテストが通りますし、自分がパーミッションを持っていないpackageが含まれていたらテストが失敗するので、パーミッションの持ち主に連絡して必要なパーミッションをもらうか、package名がかぶっている場合はお手元のpackageを修正する、あるいはMETAファイルの設定にno_indexを追加して索引に登録されないようにする、等の手段を講じてください。

Test::PAUSE::Permissionsは、METAファイル内のx_authorityというフィールドの値があればそこからリリースする作者のPAUSE IDを取得します。また、各.pmファイルに $AUTHORITYという変数が指定されていればそこからIDを取得します。どちらもない場合、モジュールのリリースにCPAN::Uploaderなどを使っている方ならホームディレクトリに.pauseという設定ファイルがあると思いますが、そこからIDを取得します。それすらもない場合は、テストをスキップします。また、このテストをツールなどで自動生成する場合は、all_permissions_ok()の引数としてPAUSE IDを渡してやれば、.pauseにそのIDが登録されているかのように振る舞います(ただし、ここで渡したIDよりも、x_authorityおよび$AUTHORITYの指定の方が優先されます)

修正: miyagawaさんにご指摘いただいて、0.04からはx_authority等をテストの対象に含めるのをやめました。情報自体は取得しますが、テストは.pause (およびall_permissions_ok()の引数)で指定されたPAUSE IDに対してのみ行います。

Perl QA Hackathon 2014に参加してきました

今回は特に予告を書きませんでしたが、昨年、一昨年に続き、今年も3月13日から16日までフランスのリヨンで開催されたQA Hackathonに参加してきました。すでに多くの方がまとめ記事を書かれているので詳細はそちらをご覧いただくとして、今年は、昨年ランカスターで議論したことを肉付けしてPAUSEなどの実装に落とし込むという位置づけの年だったこともあり、細かい点で突っ込んだ議論は多々あったものの、昨年のように「ここがこう変わるから注意してください」とみなさんに報告しておかなければならないことはなかったかと思います(古いディストリビューションなど最近のベタープラクティスにしたがっていないディストリビューションをアップロードする際に多少の注意が必要になったことや、package NAME BLOCKの形式が正しくPAUSEに認識されるようになったことなど、細々とした挙動の変化はありますが、これは重箱の隅をつつくような話でしょう)。

私もおおむねその流れにしたがって、CPANTSにPAUSEのパーミッションまわりの情報を組み込んでみたり(まだ不完全ですが、no_unauthorized_packagesというメトリクスを追加しています)、PAUSEの問題点を修正したりしていました。また、Neil Bowers氏のCPAN Dashboardをはじめとする一連の統計情報についての情報交換をしたり、マーケティングの一環?としてのCPANを256倍楽しめるようにする方法みたいな話を横で聞いたり、DBD::SQLiteについてのやりとりもありました。もっと話をしてくればよかったなあと思うことは多々ありますし、ネットワークにつながらなくて往生したとか、活動時間があわなくて苦労したとかもありましたが、プライベートも含めて、充実したハッカソンであったことです。あらためて主催・運営にあたった方々とスポンサー各社に感謝します。

以下、公開私信。

  • 夕食時にmoznion氏のGrantの件が話題になっていました。コメント欄にもある通り、好意的な意見が多くてほっとしたことです(半分くらいはHackathonの参加者からのコメントです)。
  • 具体的な話まではしてきませんでしたが、CPAN Testersのミラーの件、日本に置きたいなら手伝うし、いい考えだと思う、とは言ってもらっています。
  • 口頭では紹介したことがあるような気もしますが、http://cpan.cpanauthors.org/ はいわゆるリアルタイムミラーです。スペックはともかく国内の専用サーバでホストしていますので、CPAN Testersのサイトなどでは遠くて遅い、という方はお試しくださいませ。
  • 来年はベルリンだそうですよ。

MojoliciousとWebSocketとiTunesと

これはMojolicious Advent Calendar 24日目の記事です。

iTunesに英語教材などを放り込んでエンドレス再生していると、「ここにテキストが表示されていればいいのになあ」と思うことがあります。あるいは、洋楽を流しっぱなしにしているときに、ふと聞き取れなかった歌詞を確認したくなるとか。

もちろんその都度メモなりなんなりを開いてもいいのですが、いちいち該当のトラックに関係のあるファイルを探すのも面倒ですから、トラックが変わるたびに自動でテキストが表示されるようにしたいものです。GUIをごりごり書くのは面倒ですし、ターミナルに流し続けるのも見づらいですから、ここはテキストはブラウザに表示することにし、WebSocket経由で更新し続けるようにしてみましょう。

Windows環境では以下のようにWin32::OLEを利用することでiTunesからトラック情報を取得できます(Mac環境の場合はCPANMac::iTunesというモジュールがあるようですので、適宜読み替えてください)。

use Win32::OLE;

my $itunes = Win32::OLE->new('iTunes.Application');
my $track = $itunes->CurrentTrack;
my $name = $track->Name;
my $album = $track->Album;
my $path = $track->Location;

Mojoliciousには特定の処理を繰り返す仕組みが用意されていますので、ここではそれを利用して、毎秒iTunesのカレントトラックを確認し、変更があったら関連するテキストファイルを読み込むことにしましょう。

use Mojolicious::Lite;
use Mojo::Asset::File;
use Mojo::IOLoop;
use File::Basename;

my $current;
Mojo::IOLoop->recurring(1 => sub {
  my $track = $itunes->CurrentTrack or return;
  if (!$current or $current ne $track->Name) {
    $current = $track->Name;
    my $album = $track->Album;
    my $basename = basename($track->Location);
    $basename =~ s/\.m4a$/.txt/;
    my $textfile = app->home->rel_file("text/$album/$basename");
    my $text = Mojo::Asset::File->new(path => $textfile)->slurp;

  }
});

続いて、WebSocketまわりの処理を実装します。ここではWebSocketの接続を%clientsという変数に保存して、あとでループの中から利用できるようにしています。

use Mojolicious::Lite;

get '/' => 'index';

my %clients;
websocket '/connect' => sub {
  my $self = shift;
  my $id = "".$self->tx;
  $clients{$id} = $self->tx;

  $self->on(finish => sub {
    delete $clients{$id};
  });
};

app->start;

あとはループの中で、更新された情報をJSONにくるんで送り出してやり(cp932でdecodeしているのはもちろんWindows環境だからです)、

use Mojo::ByteStream 'b';
use Mojo::JSON 'j';

Mojo::IOLoop->recurring(1 => sub {
  if (!$current or $current ne $track->Name) {
    ...
    my $text = Mojo::Asset::File->new(path => $textfile)->slurp;

    my $json = b(j({
      title => b($current)->decode('cp932'),
      text => b($text)->decode('cp932'),
    }))->decode;
    $clients{$_}->send($json) for keys %clients;
  }
});

その情報をJavaScriptで画面に書き出してあげれば完成です。

@@ index.html.ep
<html>
<head>
%= javascript '/mojo/jquery/jquery.js';
%= javascript begin
$(function(){
  var ws = new WebSocket('<%= url_for('connect')->to_abs %>');
  ws.onmessage = function(msg) {
    var res = JSON.parse(msg.data);
    $('.title').text(res.title);
    $('.text').text(res.text);
  };
});
% end
</head>
<body>
<h1 class="title"></h1>
<pre class="text"></pre>
</body>
</html>

このようなWebSocketを使ったMojolicious::Liteアプリは、ChromeなどWebSocket対応のブラウザでないと正しく動作しませんし、現状ではplackupも、Windows環境の場合はhypnotoadはもちろん、morboさえも使えない(perl myapp.pl daemonならOK)という、なかなか厳しい制約はありますが、WebSocketを使うと、手元のブラウザだけでなく、ネットワーク上の他のブラウザでも同じ内容を表示させられますので、表示する内容を工夫すればなかなかおもしろいこともできそうです。

全体像は https://github.com/charsbar/lyrics_viewer_win32 からどうぞ。

世界の名酒事典2014年版

Perlとは何の関係もありませんが、今年からかれこれ20年近く読者の立場で愛読してきた『世界の名酒事典』の執筆作業にたずさわるようになりました(ブランデー、スピリッツ、リキュール担当)。もっとも、執筆といっても、偉大な前任の福西先生がすでに膨大な原稿を残してくださっていますし、私以外はもう何年、何十年と名酒事典の執筆にたずさわっておられるベテランの方ばかりですので、私がしたのは、年月とともに古くなっていた数字等の事実関係の更新や、扉を含む各項目の字数調整くらいのものですが。先ほど見本も届きましたので、宣伝もかねて、ご報告しておきます。

世界の名酒事典 2014年版

世界の名酒事典 2014年版

Fukuoka Perl Workshop #24

YAPCの楽しみのひとつに、ふだんなかなかお会いする機会のない方々との旧交をあたためるというものがありますが、今年は残念ながら福岡の方々があまりいらしていなかったようだったので、これはもうこちらから会いに行くしかないっしょ、というわけで、昨年に引き続き、今年もFukuoka Perl Workshopに参加してきました。台風騒ぎで一時はどうなるかと思いましたが、ふたをあけてみれば、素晴らしいネタを披露してくださったdebility@Fusicさんをはじめとする地元福岡の方々に加えて、首都圏からは講師としてyusukebeさん、関西(?)からは2週間前にも天神Perlに来ていたはずのpapixさんも集まり、懇親会では前回お会いできなかったdragon3さんにも再会できて、楽しい時間を過ごせたことです。主宰の津留さん、会場を提供してくださったヌーラボさん、参加されたみなさん、お世話になりました&ありがとうございました。

今回も昨年同様YAPCレポートの回ということで、何を話すかいささか迷ったのですが、昨年CPANTSの話をさせていただいたご縁もあったので、今回もYAPCで話したCPANTSネタの続きとして、今年あきらかにCPANTSで100点満点をたたき出す日本人作者が増えた一因と考えられるMinillaの利用状況や、Minillaの基本的な使い方を、自分がいつものWindows環境で使ってみてハマったところ、ソースを見ないとわからなかったところなども注記しながらざっくりまとめてみました。

今回のMETA generatorの統計については、一部の非常に多産な方々の影響をいっさい考慮していないので、あくまでもネタとして楽しんでいただければと思いますが(時間ができたらそのうちもう少し細かく分析してみたいとは思っています)、興味をお持ちの方のために、追加情報として、今年10月15日時点ですでに100件以上のリリースをした日本人作者のPAUSE IDとリリース件数を下記に残しておきます。なお、50件以上リリースになると下記の方々含めて11人、30件以上で17人、20件以上で26人、10件以上だと52人となります。

  • TOKUHIROM (471件)
  • MIYAGAWA (277件)
  • INA (239件)
  • KAZEBURO (126件)
  • BAYASHI (105件)
  • YTURTLE (105件)

また、当日いくつかの点についてtokuhiromさんにpull requestを送ったことを話しましたが、今日の段階ですべて取り込んでいただいて、v0.8.1としてリリースされています。ありがとうございます。> tokuhiromさん

CPAN(TS)とランキングの件、他

朝も早うから雑多な話を駆け足で詰め込んだので、消化不良になった方も多かったろうと申し訳なくも思っていますが、ポイントは、CPAN本家のFAQからたどれる「CPANにアップロードする方の責務」についてのこの一節(「私たちはみなさんも空気を読んでくれるものと信じています」)と、

Your duties, the basics, traps

We trust that you have read the perlmodinstall, perlmodlib, perlmodstyle, and perlnewmod manpages and that you regularly check out uploads to CPAN and that you have been watching CPAN activities for a while to have an impression of how things fit together. It usually boils down to (slogan shamelessly stolen and adapted from sudo(1)):

1. Think, better even talk before you upload
2. Respect the namespace of others

CPANディストリビューションの作成やインストールを助けるツールについては、miyagawaさん(Milla)やtokuhiromさん(Minilla)、Ricardo Signesさん(Dist::Zilla)のように、Perl-Toolchain-Gangに属していたり、QA Hackathonに来ていたりする人たちがいまも積極的にメンテしているツールを使ってくださいませ、という二点だけです。

CPANは、インストール前にMakefile.PL/Build.PLといったスクリプト(要するに、任意のコード)の実行を許しているということも含めて、かなりの性善説と、ツールチェーンまわりを整備している方々の不断の努力に依存しています。かれこれ20年近く続いているサービスであるだけに、過去にはいろいろ問題のあるディストリビューションもありましたし、それを受けてさまざまな対策がとられてはいるのですが、なるべくならアップロードする側のみなさんにも、最低限、最近のディストリビューションらしい体裁とか、モジュールの階層、メタ情報もろもろを整備していただけると、QAチームの一員としては大変ありがたいですし、よくわからなかったら、過去の事情にも明るい(同じ問題を繰り返さないであろう)人たちがメンテしているツールを使う方が安心ですよ、と。

ちなみに、miyagawaさんが警鐘を鳴らしてなおModule::Install 1.04が残ったままになっているディストリビューションは以下の通りです。

同じく、MYMETA.*が残っているのはこちら(リポジトリにMANIFEST.SKIPがあるならそれを修正。ない場合はリリース前にExtUtils::Manifestを最新版に更新してください)。

CPANTSについては、春のQA Hackathonの成果もあわせると、以前に比べてチェック項目が6増12減し、以前は非常に雑な実装になっていたいくつかの項目についても改善が進みました。それでもまだ十分とはいえない項目も残っていますが、最初から新しいツールを使ってモジュールをリリースしている若い世代が増えたおかげもあって、数年来続けているランキングについては、9/20時点では11人(その後さらに手入れをした方がいて、9/30時点では13人)の日本人CPAN Authors (5ディストリビューション以上)が満点で並ぶようになっています。最新の様子はacme.cpanauthors.orgからご確認いただければと思いますが、記録として、ここにもIDとお名前を残しておきます。

全日本最強CPAN Author決定選手権 2013年版 結果

1. BAYASHI (Dai Okabayashi) (↑)
2. SONGMU (Masayuki Matsuki) (new)
3. YAKEX (Yasutaka ATARASHI) (new)
4. MOZNION (Taiki Kawakami) (new)
5. AKIYM (Takumi Akiyama) (newb)
6. SYOHEX (Syohei Yoshida) (new)
6. SYAGI (Satoshi Yagi) (new)
6. ZIGUZAGU (Hiroshi Sakai) (new)
6. CHIBA (Masahiro Chiba) (↑)
10. ANAZAWA (Ryo Anazawa) (new)
10. PAWAPAWA (Kohei Yoshioka) (↓)
10. MORIYA (MORIYA Masaki) (↓ ただし1年以上更新なし)
10. RINTARO (Rintaro Ishizaki) (new ただし1年以上更新なし)

(※スコアは全員100点。順位はディストリビューション数によるもの)

訂正: 日本人CPAN Authorの抽出に問題があり、上記のリストからはHIDEAKIO (Hideaki Ohno)さんが漏れていました。掲載後、順位に変更が出ているためリストの修正はしませんが、MOZNIONさんと同スコアの4位相当です。大変失礼しました。

その他、ごく個人的なこととして、昨年ちょっと話を振ってみたら今年スライドの翻訳を一手に引き受けてくださったktatさん(と、ご同僚の方。お名前を伺いそびれてしまいました)に感謝します。なんだかんだで2006年から毎年なにがしかのスライドを訳してきたわけですが、今年はじめて手離れしました。あと、HackathonをまとめてくださったmyfinderさんとFreakOutのみなさまにも。おかげさまで(半年遅れですが)ようやくQA HackathonのTokyo Sateliteにリアル参加できました。その成果についてはまた別項で。

DBD::SQLite 1.41_01

SQLite 3.8.0 が出たので、DBD::SQLiteにバンドルされているライブラリも更新して、1.41_01としてリリースしました。SQLite 3.8.0ではクエリプランナーが一新されているほか、where節で限定する部分インデックスも利用できるようになっています。

新しいクエリプランナーの詳細については下記をどうぞ。

http://www.sqlite.org/queryplanner-ng.html

私自身はまだ使い込んでいませんが、SQLiteの作者氏によれば、sqlite.orgで2ヶ月以上使ってみたけれども問題は出ていないとのこと。DBD::SQLiteのテストから判断する限り、今回の変更によって余分なsortがひとつ減ったりしていますので、通常は新しいクエリプランナーの方が多かれ少なかれよい結果が期待できるはずですが、前回のクエリオプティマイザ最適化のときにもあったように、既存のコードのなかにはドキュメントにない、未定義の動作を前提にして書かれているものがあるかもしれませんので、安定版をリリースするまでに、アプリが壊れたり、性能劣化が起こっていないか、確認をおねがいします。

部分インデックスについては下記をどうぞ。

http://www.sqlite.org/partialindex.html

これも、上手に使えば非常に便利そうですが、3.7.0で導入されたWALモード同様、使うとバージョン3.8.0より前のSQLiteではアクセスできなくなりますのでご注意ください。DROP INDEXで部分インデックスを消せば古い(DBD::)SQLiteでもアクセスできるようになります。

また、今回のリリースではURI形式のデータベース名も渡せるようになっています。といっても、リモートのデータベースにアクセスできるようになったわけではなく、クエリパラメータを追加することでSQLiteの挙動を変更するためのものです。

利用可能なパラメータについては下記をどうぞ。

http://www.sqlite.org/uri.html

PODにも書いておきましたが、URI形式のデータベース名を使う場合は、

  my $dbh = DBI->connect("dbi:SQLite:uri=file:$path_to_dbfile?mode=rwc");

のように、従来の「 dbname= 」ではなく、「 uri= 」を使ってURIを渡してください。今回新設したsqlite_open_flagsアトリビュートにDBD::SQLite::OPEN_URIを渡すこともできます。

なお、こちらで報告しそびれていましたが、1.40ではstatistics_infoが使えるようになっているのと、NetBSDも_XOPEN_SOURCEのハックが不要と判明したので修正してあります。