forkanartを支える技術

forkanart という絵をフォークするという絵を描く人向けのサービスをリリースしたのですが、今回はその裏側の技術的な話をします。

ざっと構成を列挙します。

フロントエンド:

バックエンド:

アプリケーション:

デプロイ:

これ以外にもありますが、大雑把にこんな感じになってます。

フロントエンド

リクエスト -> nginx -> varnish -> uwsgi という特に珍しくもない構成です。
nginxをフロントに置いているのはvarnishがhttps通信を扱えないからです。 今forkanartは全部httpなのですが、将来的にhttpsに対応させる予定があるためこのようにしています。
蛇足ですが、nginxはグローバル80番、varnishはローカル8080番、uwsgiはローカル8081番の待受としています。

また、元々アプリケーションサーバーはgunicorn + meinheldを使う予定でしたが、まだloggingモジュールに対応していないとのことでuwsgiを使うことにしました。

バックエンド

MySQLはユーザー情報、MongoDBはそれ以外という使い分けをしています。
forkanartは画像のタイトルやコメントの変更がシームレスに出来るようにしているので、その部分はMongoDBみたいなwriteが速いデータベースが適切では?という理由です。ただ、今後色々やることも考えるとユーザー情報は信頼と実績のMySQLに置くようにしました。

アプリケーション

言語はPythonフレームワークはPyramidを使っています。Pyramidは前にも中規模サイトを作る際に使用したので勘所が分かってたというのもあって今回も使いました。
PyramidはDjangoと違って全部入りではないので、データベース接続部分やフォームライブラリを別途用意しなければなりません。 データベース接続はMySQLと繋ぐのはSQLAlchemy、MongoDBと繋ぐのはmongoengineを使っています。SQLAlchemyはオーソドックスとして、MongoDBの接続用ライブラリは他にも色々探したのですが、中でも一番良さそうだったのがmongoengineでした。
フォームライブラリはWTFormsを使っています。Pyramidであればcolander + deformが定番みたいな感じですが、フォームライブラリにデザインを合わせないといけないような感じで柔軟性がないので採用しませんでした。

テンプレートエンジンは mako で、CSSPySCSS + pyramid_scssJavaScriptGoogle Closure Compiler でminifyしています。

デプロイ

手動でデプロイしてしまうと更新できていないなどのミスが出てくる可能性があるので自動にしています。
Pythonでのデプロイツールの定番であるFabricに加えて、環境構築用ライブラリのalnairを使用しています。 alnairは自分が開発しており、実の所forkanartの環境構築のために開発しました。

その他

ツイッターログインの部分はvelruse (https://github.com/bbangert/velruse/)を使っています。このvelruseはpypiに上がってるものは古過ぎワロス状態なのでgithubにあるものを使っています。その他にもfacebookgithubOpenIDなど色々対応しています。


ざっとこんな感じになっています。事例として何かしらの参考になれば。

kyoto.pyハッカソンを開催しました

http://partake.in/events/e3d3bf78-0d02-4f7e-86eb-93e2d685b050

予定より大幅に遅れた感がありますが、kyoto.pyとして初めてのハッカソンを開催しました。
会場提供は 京都リサーチパーク さんです。

今回は特に縛りを設けずに、個々人でやりたいことをやるという方向にしました。

私は pyroonga のsuggestサポートの実装をしました。
ですが、30%ほどしか出来なかったです。現在も進行中なので、そのうち上げる予定です。
他の方はBlenderだったり、PythonからOCamlにアクセスするためのインターフェースを作ったりしていました。

ハッカソン自体は全員やることが違うこともあって黙々とやっていました。
また、集中してやってたというのもあり、写真とか撮ってないです。
また、当日に参加していただいた方がいたり、今回の会場を都合していただいた京都リサーチパークの方経由で外国人の方が様子を見に来たりしました。

kyoto.pyとして次回はお花見をしようと言う話になっていたりするので、4月中頃にやるかなといったところです。

京都Vim勉強会#1を開催しました

http://partake.in/events/f2afeb6f-aad1-40b3-b067-fbee40822c06

何気に関西でVim勉強会あんまりないなーと思ったので開催してみました。
会場提供はいつもの 京都リサーチパーク さんです。いつもありがとうございます。

最初の発表は [twitter:@kyubuns] さんです。

Vimを使い始めて半年ほどということでしたが、プラグインを作ってしまう辺りすごいですね!

2番目は [twitter:@kuri65536] さんです。

http://kuri65536.bitbucket.org/kyotovim-01-120324.html

2部構成になっていて、前半は「VIMとモバイル環境について」、後半は「変わり種plugin紹介」でした。
スライドを SphinxS6テーマ で作成していました。
私自身モバイルは疎いのですが、とにかくいろんなモバイル機器でVimが動くということです。
ただ、機種によってはESCキーもCtrlキーもないため、インサートモードに入るとどうしようもなくなる罠があるそうです。

3番目は [twitter:@_likr] さんです。

スライドの代わりに Unite.vim を使った Unite.vim についての発表でした。
Unite.vimは説明するより実際に動かしているのを見たほうが分かるということで、このようにしたそうです。
最終的に :help Unite を見れば説明することは何もないらしいです。ですよねー。

4番目は [twitter:@aizen76] さんです。

スライドなどは特に無く、実際に操作をしながらVimのプログラミング環境についての発表でした。
大体 vimshell と Unite.vim だったような印象でした。
あとは日本語入力にSKKを使っていて、勉強会終了後にその話題で盛り上がっていました。
また、vimshellで実行できないものもやはりあるようで、そういうときは Conque Shell というものを使っているそうです。初めて聞いた。。。

最後は私、 [twitter:@naoina] です。

まぁ、 syntastic という多くのファイルタイプをサポートしている構文チェッカーの紹介だけできればよかったので、あとはおまけです。
紹介した各プラグインについて知ってる人に手を上げてもらいましたが、各プラグインすべてで知っている人は少ない感じでした。

今回は午前中だけでの開催でしたが、もっと時間を長くしてもいいかなと感じました。
また、私が発表自体をメモするのを忘れていて、記憶に頼ったかなり偏ったレポートになっていると思います。書記を担当してくれる方も欲しいですね。
Ustreamでのストリーミング配信は、京都リサーチパークさんの会議室の環境がいい(電源、LAN完備)ため可能ではあるのですが、 めんどくさい一人で全てするのはちょっと大変だったので今回は見送りました。



素晴らしいろくろ回しです。

次回の開催は未定ですが、いつかはVimの [twitter:@ShougoMatsu] さんに関西で歌っていただきたいと思っています。参加費で賄えば交通費ぐらいは出せるかな。
というわけで、参加していただいたみなさん、ありがとうございました。

複数バージョンのPythonでのテスト

最近 pyroonga というPythonから groonga が操作できるようなものを作り始めたのですが、作るにあたってサポートするPythonのバージョンを2.6、2.7、3.xに決めました。

そこで問題になるのがテストです。複数バージョンでテストしないといけないので、virtualenvあたりを使うんですが、いちいちバージョンを切り替えてテストを走らせるのがめんどくさいです。

で、そのためのツールに tox というものがあります。これを使うと複数バージョンでのテストがコマンド一発で済みます。

前提条件として、テストに使用するバージョンのPythonがシステムにインストールされている必要があります。 まぁ普通のPythonistaならPython2.6、2.7、3.2ぐらいは当然入れていると思いますので問題ないでしょう。

インストール

pipまたはeasy_installを使ってpypiからインストールできます。

% pip install tox

or

% easy_install tox

使い方とか

例として以下のようなディレクトリ構成になっているとします。

ディレクトリ構成:

.
|-- example
|   |-- __init__.py
|   `-- tests
|       |-- __init__.py
|       `-- test_example.py
|-- setup.py
`-- tox.ini

toxを使用するにはsetup.pyが必要なので、適当に用意してください。

tox.ini はsetup.pyと同じディレクトリに置きます。

# tox.ini
[tox]
envlist = py26,py27,py32

[testenv]
deps = nose
commands = nosetests []

envlist がテストに使用するPythonのバージョンです。前述の通り、既にシステムにインストールされている必要があります。pypyやjythonも指定できたりします。

deps はテストに必要なパッケージを指定できます。ここに書いたものはtoxが自動的にpypiから持ってきてくれます。

commands にテストを実行するコマンドを書きます。 [] にはtoxを実行するときの引数が入ります。

以下のコマンドでtoxを実行します。

% tox

nosetestsに引数を渡してやりたい場合は

% tox --with-doctest

これで、tox.ini と同じディレクトリに .tox というディレクトリに envlist で指定した各バージョンのvirtualenvが構成されてテストが走ります。

特定のバージョンのテストだけ実行したい場合は -e オプションを付けて

% tox -e py26

とします。

テストが実行された後は、どのバージョンでテストが失敗したかなどが分かります。

% tox
_____________ [tox sdist] _____________
...

____________ [tox summary] ____________
[TOX] ERROR: py26: commands failed
[TOX] py27: commands succeeded
[TOX] py32: commands succeeded
%

さらに詳しく知りたい場合は公式サイト http://tox.testrun.org/latest/ を見てみてください。

zshのvcs_infoの挙動のお話

zshvcs_infoについての備忘録。

vcs_infoというのはzshのプロンプトに今いるリポジトリの情報を表示してくれるものです。

zsh で Git の作業コピーに変更があるかどうかをプロンプトに表示する方法

これすごく便利なんですが、異なるVCSリポジトリがネストした状況下で想定した動作をしません。
例えば $HOME (~/) 以下をバージョン管理している状況でその下に個別のバージョン管理しているプロジェクトを置いている場合などです。
vcs_infoの設定を以下のようにしている場合

zstyle ':vcs_info:*' enable git hg
zstyle ':vcs_info:*' formats '(%s:%b)'
PROMPT="%1v%# "

gitリポジトリ以下にmercurialリポジトリを作成してcdした場合にプロンプトの表示がgitのままになります。

% git init top-repo && cd top-repo
(git:master)% hg init nested-repo && cd nested-repo
(git:master)%

これはvcs_infoが zstyle ':vcs_info:*' enable git hg の先頭から順に調べて行って、そのVCSリポジトリが見つかった時点で確定するためです。
gitやmercurialなどはカレントディレクトリにリポジトリが見つからない場合、上の階層に向かって再帰的に探すようになっています。そのため、前述のような動作になるわけです。

実際のコードは /usr/share/zsh/functions/VCS_Info/vcs_info の138行目辺りにある以下のコードです。 *1

...

for vcs in ${enabled} ; do
    [[ -n ${(M)disabled:#${vcs}} ]] && continue
    if (( ${+functions[VCS_INFO_detect_${vcs}]} == 0 )) ; then
        printf 'vcs_info: configured unknown backend: '\''%s'\''\n' ${vcs}
        printf 'vcs_info: use '\''vcs_info_printsys'\'' to find supported systems.\n'
        continue
    fi
    vcs_comm=()
    VCS_INFO_get_cmd
    VCS_INFO_detect_${vcs} && (( found = 1 )) && break
done

...

これの解決策としては、ネストしてるリポジトリの一番上のVCSvcs_infoのenableの一番後にもってくれば大丈夫です。
本家ML(http://www.zsh.org/mla/users/2011/msg00676.html)にもありますね。

*1:zsh 4.3.12の場合

kyoto.py Pythonハンズオン開催しました

http://partake.in/events/bafb8661-269f-4b81-9444-2b6a9981b44a

kyoto.py としては初となる勉強会を開催しました。kyoto.pyというのは、関西圏でのPythonコミュニティです。kyotoなのは、発起人である私が京都にいるからで、活動自体は関西圏全体です。
今回も会場は 京都リサーチパーク さんの提供でした。いつもありがとうございます。

また、今回はハンズオン形式での開催で、

の3つのハンズオンがありました。Pyramidは私[twitter:@naoina]、PyOpenCLは[twitter:@_likr]さん、テスト駆動開発は[twitter:@aroma_black]さんがそれぞれチューターを担当しました。
どのハンズオンに参加するかはチューターからどのようなことをやるのかを発表してもらって、それによって決めるという方法を取りました。



私がチューターをしたPyramidを知っている人が3人のチューターしかいなかったので1人ハッカソンかと思われましたが、参加してくれる方がいてぼっちは回避できました。

こんな感じでした。

私がチューターのPyramidハンズオンの内容としては、Pyramid公式のチュートリアルを行うというものでした。それに際してGoogle翻訳さんに頑張ってもらい、公式チュートリアルを翻訳したものを使用しました。しかし準備時間が足りず、すべては翻訳できませんでした。

http://handson.kuune.org/tutorials/wiki2/

また懇親会は全く考えていませんでしたが、全員があれば参加したいということでしたので急遽こちらの会場も取りました。

今回は Mashup Awards 7 のMashup Canvas & Meetup in Kyotoと日程が被ってしまったにも関わらず、参加いただいた方々、本当にありがとうございました。 またこういうイベントを開催したいと思いますので、見かけたらよろしくお願いします。

Buffalo WLI-UC-GNをLinux 3.0で使う

以前に安定動作させるために頑張った Buffalo WLI-UC-GN ですが、Linux 3.0で動かなくなったので動かすまでの備忘録。

環境:

不具合:

  • そもそもデバイスを認識してくれない
  • rt2870staを入れても認識しない(ように見えた)

調べて分かったこと:

  • なんかArch LinuxwikiじゃLinux 3.0のrt2800で使えてる的なこと書いてる *1
  • どうもrt2870staはrt2800usbに置き換わった *2 らしい

解決方法:

  • 以前に追加した /etc/modprobe.d/modprobe.conf のblacklistを削除
  • ifconfig wlan0 up をすると何故か
# ifconfig wlan0 up
SIOCSIFFLAGS: Operation not possible due to RF-kill

と言われるようになっていたので、有線LANを繋いでrfkillを入れる。

% yaourt -S rfkill
  • rfkillを /etc/rc.conf のDAEMONSに追加
DAEMONS=(@rfkill ...)

結果:

  • (今の所)2.6.3xの時より安定している

まとめ:

Arch Linux wikiは神