※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

Python Developers Camp2008参加メモ



このページでは、長野県松本市で行われたPython Developers Camp2008冬で学んだことを記していきます。

■開催概要
 名称 Python Developers Camp 2008 冬
 日時 2008年3月7日(金)〜9日(日), 二泊三日
 場所 松本ホテル花月
 対象 Pythonに興味のある方(合計41名)
 主催 Python Developers Camp 2008 冬実行委員会

注意
議事録ではなく自分の気づいたことのノートなので、抜けとか
自分の意見が混じっています。その点はご了承ください。

最終更新日: 2009年06月01日 ;

プログラム

1.自己紹介

自己紹介の中で気づいたこと、気になった人
渋川さん
テストファーストが大好き。MindMapもキレイに書きこなしていた。
大川さん
製薬系の人はPythonを使う人が多い。ライブラリが豊富なことが理由らしい。(Rubyは少ない、とのこと)
根本さん
iPhone(脱獄済み)を持ってました!いろいろ見せてもらい、自分のiPod touchと比較。カメラ機能があって、写真を撮った後に写真閲覧モードにシームレスに移動していたところに感動。おもてなしの美学だなあ。
小吉さん
Python1.4から使用している方。総務なのに、Pythonを業務に使用して役立てているとのこと。
西尾さん
Jython本を書いているとのこと。いつ頃でるのかな?楽しみだ。(飲み会での追記:最短で4月らしい)
メモ
大学生なのに仕事を兼業でやっている、という人が複数いて
びっくり。自分の大学生のころは遊んでばかりだったので、
言い聞かせてあげたい(→過去の自分に)
電子工作とPylonsに興味のある方が多い(実際、2日間ずっと
会議室の中で「島」を作って作業をしていました)。
初心者が多いのも、実は意外だった。
もっとPythonエキスパートばかりで気後れしそうな予感
だったので、ちょっと安心。←小心者

メモ
西尾さんはMacBookをキャンプ3日前に購入したので、
JythonだけでなくPyObjCについても突っ込んでいって
ほしいところ(ボソボソ)

Mac率、Thinkpad率が異様に高いのも印象的でした。そうだ、MacBookAirもいた!初めて見たけど薄いわ、これ。ほしい・・・。

2.体験テストユニット --- 渋川さん

■1日目
重要なキーワードは、

  「 最初、テストは必ず失敗すること

ということ。『テスト(失敗)→実装→テスト(成功)→リファクタリング→テスト(失敗)→・・・』を繰り返して、「 汚い・動かない 」から「 きれい・動く 」に持っていくことが大事。早いサイクル・大きすぎない粒度で回せるとよい。

■2日目
渋川さん作成のpySpecを使用してセッション開始。Google Groupの中からダウンロードしたpySpecのソースにはバグがあるらしく、インストール後のファイルLib/site-packages/pyspec/cui/addin.py内の、
import os
import sys
import imp
 
import wx
from wx import xrc
 
import pyspec.addin
 
にあるwx系を削除しておくことが必要だった。
import os
import sys
import imp
 
import pyspec.addin
 
として、Save。

そういえば、このセッションでは隣の方とペアを組んでプログラミングをした。面白かったのが、まずは2分でお互いを自己紹介+決意表明した上で作業を始めたこと。自己紹介の前後では、「隣人の決意表明を手助けしてやろう!」という目的意識が生まれているのに気がついた。
eXtreme Programmingってきっかけ&モチベーションの維持が大事なんだなぁ。
とはいえ時間がなかったのでスライドをベースに説明をしてもらうのがメインのセッションとなってしまった。本来なら半日かけて行う作業なんだと思う。

「BDD」という新しいキーワードを学んだ。Behaviour Driven Development。懸田氏の翻訳記事にあるように、「Test/Assert(試す/断言する)」ではなく「Should/Verify(こうあるべき/検証する)」を意識したテストケース *1 を作成することが大事。

オブジェクト指向設計における、
  • 事前条件
  • 事後条件
を、どうあるべきかという振る舞い(Behaviour)として記述することで、それがつまりテストであり、仕様になるという結果を生む。「契約による設計」なんだね。

これらをpySpecではテストケースとして、
  • 「@context」で事前条件(クラスの作成、テストのための準備)
  • 「@spec」で事後条件(こういうメソッドを呼んだ後は、こうあるべき)
を記述するようになっている。
メモ
渋川さんは、「開発者のためのテストケース」と、「テスターによる
テストケース」とをいずれは一緒にしたいという夢があるらしい。
うん、それは両者にとって理想の姿だ。「一緒」という定義には
紛糾するかもしれないけれど。

あと、 MockとStubとは違う ということは初めて知った。まだよく分かっていないので、これは渋川さんに聞いておかなければ。

追記:
聞いてきた。Mockは親(呼ぶ側)が何をするか、たとえば
どういう順序で、どういう値を渡すかを判断し、検証して
くれるもの、とのこと。逆にチェック機能のない、単なる
木偶のようなものがStub。つまり
⇒ Stub = Mock - (検証機能)
という関係。
ちなみにJavaの開発・テストだと、Mockがないと話にならないらしい。

あと、docstring内にインタプリタでの振る舞いを書くdoctestというモジュールの説明してくれたけれど、これはまあ、おまけみたいなものだからスルー。一応書くと、
  • ○:分かりやすい、気軽。
  • ○:他人のコードでも何を意図しているかがdocstringだけで分かる
  • ×:網羅的なテストは書けない
  • ×:各テストが別々にできない(シーケンシャルに実行)。ステートフルになってしまう。
  • ×:結果が毎回変わるようなものはテストできない
というメリット・デメリットがあるとのこと。
メモ
時間が少ないのが残念だった。渋川さんとは時間をかけて、
もっと色々と聞きたい。
TODO:次にお会いするときまでに、もっと勉強しておこう。

2.1.Q&A

組み込み開発のような、サイクルを回すのが難しい(ハードが必要・サイクルを小まめに回せない)環境でTDDをするにはどうしたらいい?
開発内にはハードを用いる必要がないところがある。その部分をWindowsだったりLinuxでシミュレーションできる環境を作り上げ、そこでテストを実行するといい。スタブ・ドライバ(=モック)をも持った環境。
メモ:
どこまでスタブ・ドライバを用意するか、作りこみが重要になりそう。
組込みだとxUnitも適用し難いし、フレームワークがあるわけでもないし。
とにかく、テストサイクルを速くする為の仕組みづくりを工夫することが大事。組み込み向けにも言及している参考書籍は「eXtreme Programming実践レポート」。

開発に習熟してくると、テストする単位がどんどん大きくなっていきそうで不安。粒度で気をつけている点は?
プログラムの中で、ネジ・クギに相当する部分やボトルネックになる部分はできるだけ粒度を細かくするよう意識している。逆に、ユーザーインタフェースなどの後からコロコロ変わる部分は疎にしている、とのこと。
メモ:
細かくすることができない、というテストがあった場合は、
そもそも要求仕様の定義が不完全であることの気づきにも
なるね。

3.初心者用セッション -- 吉田さん

Pythonとは何かから始まって、インストール方法、基本的な特徴・操作方法を教えてくれた。しかも、すごく丁寧に、分かりやすく。こういうリズムでデモが出来たらいいな。

Pythonの魅力とは、
  • 予約語が少ない
  • 記号が少ない
で、つまりまとめると、「 人生の敗北者でも使えるPython --2chのコメント」なんだってさ。
2日に渡るセッションで、2日目はApacheログを解析するスクリプトを作成する例を紹介していた。このスクリプト、吉田さんがより作りこんだものをGoogle Codeで「apachelog-analysis」として公開している。

■配列のスライス
>>> a=[0,1,2,3,4,5,6,7,8,9]
>>> print a[2:4]
[2,3]
 
となる。つまり、array[m:n]はインデックスmから(n-1)のことを意味する。ちなみにa[-1]は最後の値を返すし、array[m:n:s]とした場合はsステップずつの値を取り出せる。(a[0::2] => [0,2,4,6,8] / a[1::2] => [1,3,5,7,9])

■importしたモジュールを再評価したい
Pythonでは一度importしたモジュールは、再度importしても再評価してくれない。しかしimportされたモジュールの一部を変更・保存して再importさせたい場合には『reload(module名)』とすればOK。
メモ
けれどこの方法は「from module import hoge」したものを
再importすることには使えませんでした。
この書式だとmoduleそのものとしてはインポートされていない
ためなんだそうです。

■逆順列を求める
順列のリストを求める場合、range(n)を使用するが、逆順のリスト「[(n-1),(n-2),...,1,0]」を得たい場合には次のように入力する。
>>> range(n)[::-1]
 
これだけ。Pythonのリストがスライスできる、という機能を利用した方法だけれど、目からウロコ。

■PerlのCPANに相当するPython向けサイト
「PyPi(http://pypi.python.org/pypi)」というサイトがある。CPANほど有名ではないけれど、CPANは吉田さん曰く「あそこは何でもアリスギ」なんだそう。

■rangeのイテレータ(正確にはジェネレータ)
「xrange」というfor文などに使えるイテレータがあるので、これをストリームとして使える。いてレートするたびに次の要素を返してくれるため、余分なメモリを消費しない(遅延評価の一種、か)。UNIXのパイプのような概念。
xrangeはrangeと異なり最初にリストを返さずジェネレータを返すだけなので、後からの変更が利かない(=xrange(n)[::-1]が不可能)。初期化時にジェネレータが生成するストリームを指定しておかないといけない。

9→0の逆順列の場合は、 xrange(9,-1,-1) (引数に注意!!)としてあげればよい。

■辞書内の値でソートする
a={'a': 3, 'c': 54, 'b': 30, 'd': 45}というような辞書があったときに、その値でソートしたいときの方法。
> a={'a': 3, 'c': 54, 'b': 30, 'd': 45}
>>> keys=a.keys()
>>> keys
['a', 'c', 'b', 'd']
>>> sorted_list = [(a[k], k) for k in keys]
>>> sorted_list
[(3, 'a'), (54, 'c'), (30, 'b'), (45, 'd')]
>>> sorted_list.sort()
>>> sorted_list
[(3, 'a'), (30, 'b'), (45, 'd'), (54, 'c')]
>>> sorted_list.reverse()
>>> sorted_list
[(54, 'c'), (45, 'd'), (30, 'b'), (3, 'a')]
 
「sorted_list.sort() & sorted_list.reverse()」の代わりに
sorted_list.sort(reverse=True)
 
でもいいらしい。こっちの方がスマート?


(2008/3/13追記)
jackさんのコメントで、「シンプルな別の方法」として
b = a.items()
b.sort(key=lambda x:x[1])
 
という方法を教えてもらいました。えっと、ディクショナリに対してのitems()メソッドは、『[(key1, value1), (key2, value2), .... , (keyn,valuen)]』というタプルの配列を返してくれる、と。そして、配列のメソッドsort()のキーワードkeyは「何を基準にしてソートするかを渡す」関数を与えるようになっている・・・なるほど!面白い!
ただしこのままだと昇順になってしまうので、
b = a.items()
b.sort(key=lambda x:x[1], reverse=True)
 
が正解かな。jackさん、ありがとうございます。
注意:2.4以降でないと動かないそうです。


4.Pythonで電子工作 -- 芝尾さん

Gainerを使って、その先のデバイスをPythonで動かすというクラス。ボクは参加できなかったけれど、みんなかなり面白そうに作業をしていた。
Gainerは1チップマイコンなのに、USB接続して、LED直結で光らせたりすることができるなど、かなり高性能なチップだ。

4.1.事例:ネット越しにラジコン操作

事例として、さとうしんご(id:akio0911)さんが、
「ブラウザ」⇔「Webサーバ(Ajax)」⇔「Gainer」⇔「デジQのプロポ&Webカメラ」⇔「チョロQ」というように、ネット越しに映る画面でチョロQを操作するデモを見せてくれた。素人にも分かりやすいし、これはすごい!

柴田さんのアップしたYouTube動画を載せておく。

5.Pylons勉強会 --- 小田切さん、林さん

すみません、ぜんぜん参加していないので分かりません。これはDjangoのようなWebフレームワークとのこと。

でも独自の「島」が2日間、終日できて作業が進んでいたので、興味のある人が多く、熱意を持って臨んでいる感じが伝わっていた。
今度、どんなものか調べてみよう。

6.NodeBox --- id:akio0911さん

NodeBox(http://nodebox.net/code/index.php/Home)とは、Mac OSX(Leopard)で動作する、Pythonで簡単にCG・アニメーションを作成できる開発統合環境のこと。
自分のPCがThinkPadだったので見るだけだったけれど、本当に簡単なコードできれいなCGを記述できていた。

Core ImageとPyObjCの連携を「One more thing...」で紹介。どうもNodeBoxはCore Imageとの連携で動かしているらしい。だから速いんだ。

メモ
とにかく、見た目とコード量の少なさとのギャップがすごい
ソフトだった。デスクトップだけど、Macユーザーで良かった。

追記。

2日目の夜、id:akio0911さんがNodeBox on Jythonを作って公開していた。1.5h弱でNodeBox on Jython(+SWING)をスクラッチから作ったとのこと。まだoval()しか載せていないとはいえ、すごい。
本人の技術説明を聞いていると「eval()が使えてGUI環境を持っていればできる」とのことだから、
  • NodeBox on PurePython(by Tkinter)
  • NodeBox on Gauche
  • NodeBox on RubyCocoa
  • Nodebox on PyObjC ←これがオリジナルなんだってば。
も作れるらしい。これはちょっと頑張ってみたいな。

6.1.Q&A

案の定、Q&Aも多く出ていた。
デモでコードの値を動的に変えていたけれど、どうやるの?
ソースコード中の値にマウスでポイントして、コマンド+クリックすると、値を動的に変更して、その結果を別のペインでダイナミックに確認できる。

NodeBox外部にExportできる?
可能。イメージなら何種類かの画像フォーマット、ムービーならQuickTimeで出力できる。しかもIllustratorならPDFでオブジェクトをいじったり、というのも可能

コマンドラインから実行して書き出す、みたいな自動化は可能?
今は無理だけれど、開発者たちが優先的に実装を進めているらしい。できれば一緒に。

他人の作成したオブジェクトを再利用できる?
関数にしてしまえばできる。

WindowsやLinuxで同様のものはある?
Windows版はあるけど、微妙とのこと。ただ、さとうさんがJythonでPython+Schemeで動くようなものをポーティング中。なぜSchemeかというと、フラクタルなどの自己相似図形を描くときの再帰に都合がいいから、らしい(なるほど、末尾再帰だ!)

NodeBoxで保存したときのファイル形式は何?
.py。ただし「python ~.py」では動かない。当然だけど。

メモ
人目を引くスライド・デモだったので、セッション後
会議室内に急遽「島」ができて独自に勉強会を進めることに
なってしまったほどインパクトがあるIDEだった。
ボクも家に帰ったら使ってみよう。

メモ
このソースを他のPythonスクリプトに組み込んだりできたら
最高だ。Core Animation/Core ImageのPythonインタ
フェースになるし。

7.BuildBotとSeleniumの紹介 --- 清水川さん

Webサイト構築時のテストに特化したフレームワークBuildBotSeleniumについての紹介。ごめんなさい、Webフレームワークに触ったこともないし触ることもないので良く分かっていませんが・・・

BuildBot
ビルドサーバを用意しておき、コミットをフックにして、テストユニットを実行したり、ビルドしたりで結果を時系列情報とともに記憶、ブラウザで閲覧できるフレームワーク。Pythonスクリプトをきっかけにいろいろなことができる。
Selenium
Webブラウザの操作を「録画」しておき、その再操作をテストケースとして「再生」できるフレームワーク。テキストボックスに何かを入力→ページ遷移→リンクをクリック→・・・を録画できる。ステップ実行なども可能。
デバッグ環境の充実ぶりが、組み込み屋にとってはものすごくうらやましいセッションだった。

メモ
このテスト再生をリモートPCに行わせることも可能。
Web操作が絡むものにはSeleniumってかなり便利なフレーム
ワークだなあ・・・。僕ら組み込みの、パネルを操作しないと
いけないテストの、自動化フレームワークみたいなものは
ないのだろうか。しかも無償で。

8.kVerifier,scipy,sf.pyの紹介 --- 小林さん

すみません、内容が難しすぎてよく分かりませんでした。でも、58歳にしてすごいパワーを持った人でした。
kVerfier
小林さん作成の、テスト用メタ言語によるプログラムテストのプログラム。元はC/C++向けのものだったのを、Pythonでも使えるようにしたとのこと。
scipy
http://www.scipy.orgで配布されている数値計算ライブラリ。とんでもなく頭の良い人たちが作ったすごいライブラリ、らしい。
sf.py
小林さん作成の電卓プログラム。電卓、とはいえ行列計算が得意なPythonモジュール。Matlab,Mathmatica,GDL(GNU Data Language)のコマンドライン版(on Python)というイメージが近い、かな(たぶん)。

メモ
デモをするときに小さな字のコマンドラインとエディタの
画面だけで説明するので、何をしているかが理解しにくかった。
スライドとデモの組み合わせ、でやってほしかったかな。
(理解できないことへの言い訳かも)

9.Monty Pythonで学ぶイギリス英語とPythonの思想 --- 柴田さん

Monty Pythonのムービー(あの'Spam'のオリジナルコントも!)を見ながらのイギリス英語とアメリカ英語の発音の違いを学ぶ、というセッション。

イギリス英語では「Have you taken a dinner?」というところを、アメリカ英語では「Did you ~?」と言ったり、発音記号「ae(のくっついた記号)」をイギリス英語ではあまり使わなかったり、という違いがあることを知って、存外に(失礼)有意義だった。
メモ
もう少し、発音のいろいろな違いの説明があると面白かったかな。
でも、Monty Pythonはバカバカしくて面白かった。

ライトニングトーク

1.NodeBoxについてのデモ :さとうさん

あんなに難しそうなアニメーションがこんな短いソースで書けるなんて!NodeBoxすごい!

2.WebMailのおはなし:おおたにさん

WebMailクライアントを実装してしまったらしい。大したことないということですが、普通の3ペインメールクライアントと同じような動作している!非同期で新着メールを受信してたり既読になると別ペインの数をデクリメントしたりしていた。

3.RCG(RealtimeCG)とPython:a2cさん

  • 何でもタグをつけておきたい
    • ログインした各ユーザーが、Twitterのような簡単なメッセージ、検索してきたYouTubeやFlickerの情報(同じサイト内でサムネイルが一覧表示!しかもきれいに!)に対してタグをつけ、保存できるWebサービスの例を紹介。
    • メモ帳が、Flicker,YouTubeの情報をタグと共に覚えておける、という技術。
    • スムーズな画面展開が、見ていてとても心地よかった。
      • デモではエラーが出てしまって見れなかったので、最終日に改めてお願いして見させてもらった。すごかった。A2Cさん、ありがとう。
  • リアルタイムに画像を作る
    • Brainstormを使った画像のデモ。リアルタイム&オブジェクティブ指向な画像作成ソフトウェアの紹介。
      • これはどういうソフトなんだろう?スペイン製だということだけど・・・。

4.Pythonと電子工作:芝尾さんとGainerの皆さんの作品集

  • 3次元の加速度センサーでお絵かきするプログラム
  • 3次元の加速度センサーで画像を傾けたり、倒したり
  • 3次元の加速度センサーでブロック崩し
  • 3次元の加速度センサーでお絵かきするプログラムその2
2日間の作業なのに、皆さん色々と面白いものを作っていた。それにみんな楽しそう。

5.isk-daemonについて:tokibitoさん

GPLの、類似画像検索エンジン。Pythonで作られている。「isk-daemon(http://server.imgseek.net)」
ファイルを指定すると、その特徴データをDBに入れ、Fast Multiresolution Image Queryingというアルゴリズムで類似画像を検索するとのこと。本当に似たデータが出てくるからすごい。
ちなみにプレゼンツールはamachangのs6をベースにした自作Javascript。「ちなみに」どころじゃないよ、それ。

6.WSGIの話:林さん

  • 「ウィスキー」と読むらしい
PythonにおけるHTTPサーバとアプリケーションの間を規定した仕様とのこと。アプリ・ミドルウェア・サーバの仕様を知っていれば何とかなるらしい。

それぞれの仕様のポイント説明が続いていたけれど、Webのことをよく分かっていないので分からなかった。Apacheでやっているようなこと+αを実現できるらしい。そして、入出力の仕様をしっかり決めているので、その中を自由にできることが特徴とのこと。
TODO
調べておこう。

7.virtualenv:小田切さん(aodag)

試験環境を自分のPython環境で試したところ、いろんなものが変化してしまって困った、という人のための、virtualenvというPython専用の仮想環境構築ツール。easy_installでインストールできる。
virtualenvで作った環境でPythonの実行環境を作れるので、sourceコマンドで仮想環境に入る。ここなら既存のPython環境にこだわらず、怪しいパッケージを試せる。
メモ
deactivateで汚れちまった仮想環境を削除できるとのこと

8.IronPythonでWiiリモコンから値をとる話を10分でできるところまでライブコーディング:西尾さん

本当にライブコーディングしている。説明も、途中途中でどこを参照したらよいかの説明があったり、すごいな。デモとしてもGを表現するため身体を(必死に)動かしていて面白かった。

9.pythonでFeliCaを読む:鈴木さん(http://takanory.net/takalog

パソリ
FeliCaとのインタフェース
felicalib
SONYの提供するライブラリ(Win用DLL)
ctypes
「PyTCで学ぶPython C拡張の書き方」であったdllを読み込むライブラリ
の組み合わせで作る、Pythonを使った情報の取得デモ。ユニークなIDのほかに、暗号化されていない領域(入出金管理や、SuiCaの入出履歴など)を読めていた。
  • Macだとパソリとlibpasoriというモジュールさえあればいいらしい。Windowsの方はfelicalibとcpythonのセットで必要。
ただ、EdyもSuiCaも互換性がないので、データはゴリゴリと読むしかないらしい。解読した鈴木さんはすごいな。

結論

みんなすごい!ボクも負けずにがんばるぞ!
TODO:あとでちゃんと感想書け。

その他、補足

  • 鈴木さん曰く、pyUSBという低レイヤのライブラリがあるらしい
    • USBデバイスをダイレクトにいじれるみたいだから、組み込み屋にとっては面白そう。

  • curlという1万x1万のテーブルも高速に使えるインターネットアプリ用DBがあるらしい(MITライセンスだけど、住商が販売権を握っている?)

  • pythonコマンドで始まるPythonインタープリタよりも高機能なインタープリタ「IPython」があるとのこと。readlineさえ入っていれば大丈夫なので、自分の環境にも入れてみよう。
    • Tabキーでメソッド補完ができたり(!)
    • 'メソッド名'+'?'でそのヘルプ(たぶんdocstring)が見れたりするらしい。

  • PyScripterという、Delphiで作られたWindows専用のPython用IDEがあるとのこと。
    • かなりの高機能なIDE。
    • ツリー形式でファイルやメソッドを一覧表示したり、unittestと組み合わせたときにはどのテストを実行するか(そして結果はどうだったか)を表示してくれる。
    • tokibitoさんが日本語化パッチを作っている。これまたすごい。

  • 小林さんの車に同乗させてもらったときに知ったこと。
    • Pythonは関数コールのたびにスタックフレームが確保される。
      • だからClosureが実現できるのか!
    • Closureは、作成したときの引数とそのときの環境がImmutableであることを保証してくれるから(書き換えも出来るけどね)、それこそがClosureを使うメリットになる。←Closureの使いどころに困っていた身としては目からウロコだった。

  • 最終日の朝の洋食、柴田さんだけが(間違えて)ごはんと味噌汁を自席に持ってきてしまい、洋風おかずと一緒に食べていた(ほかの人は食パン)。
    • フォークで食べていた。

参考サイト


-

コメント

もしあれば、どうぞ。参加していた方は「誤解しているよ」などの突っ込みを期待します。

  • NodeBoxについて補足。'from nodebox import console'して色々とできることを知りました。http://nodebox.net/code/index.php/Console -- akio0911 (2008-03-09 21:04:29)
  • そうなんですね。僕も色々試してみます。NodeBoxを知る機会を与えてくれて、ありがとうございました。 -- かときち (2008-03-10 21:16:05)
  • 辞書の value でのソートですが、 b = a.items(); b.sort(key=lambda x:x[1]) あたりがシンプルな気がします -- jack (2008-03-13 15:45:54)
  • ありがとうございます。参考にさせてもらいます(追記もしておきます)。 -- かときち (2008-03-13 16:19:41)
  • ああ、reverse わすれてました。すみません。ちなみに、2.3以前にはないです(keyもreverseも)。 -- jack (2008-03-17 13:57:33)
  • jackさん、たびたびありがとうございます。2.4以降、と記述しておきました。Pythonはバージョンが上がるにつれてソースがよりキレイになっていきますね。 -- かときち (2008-03-17 15:04:30)
添付ファイル