2009年12月27日日曜日

OmniFocus を軽く快適に使えるようにメンテする技

普段からGTD用ツールとしてOmniFocusを便利に活用しております。iPhoneと3G経由でいつでも同期できたり、タスクレビュー機能があったり、何でもできて凄く助かるのですが、このOmniFocusには弱点がありまして・・・

そう

重すぎ

定期的にデータベースをメンテしてあげないととんでもない重さになってしまいます。
具体的には、サーバーと同期しようとしたiPhoneが10分間固まって帰ってこなくなったり
mobileme上に置いてあるデータベースファイルを開こうとしてFinderが固まって帰ってこなくなったり
とにかく、相当な破壊力を持つ代物です。その上公式サイトにも正しいメンテナンスの仕方が書いてありません(一番大事なところが書いてない)。そこでOmniFocusユーザーの方必見(?)、OmniFocusデータベースのメンテナンス方法をまとめてみました。

参考にしたページは以下の通り。
http://forums.omnigroup.com/showthread.php?t=14631&highlight=compact
http://forums.omnigroup.com/showpost.php?p=70253&postcount=3


■予備知識:OmniFocusのデータベースの構造
OmniFocus.ofocusというファイルがOmniFocusのデータベースファイルです。その正体はMac Bundle(わかりやすく言えば単なるディレクトリ)で、中に以下のような形式でZIPファイルが入っています。
0000000000-日付.zip
ランダムな文字列-日付.zip
ランダムな文字列-日付.zip
ランダムな文字列-日付.zip
以下たくさん・・・
このZIPファイルを解凍するとcontent.xmlというXMLファイルになります。このcontent.xmlの集合がOmniFocusデータベースの基本構造になります。
content.xmlには「一番最初のデータベースの状態」か「前回保存時からのデータベース操作内容」が記載されています。要するに先ほどのZIPファイルの集合には以下のようにデータが格納されています。
このデータベースにはタスクが10個入ってるよ - 2009/11/10.zip
タスクBを完了したよ - 2009/11/10.zip
タスクXYZを新規作成したよ - 2009/11/10.zip
タスクDを削除したよ、あとコンテキストXXXを作成したよ - 2009/11/12.zip
これらのZIPファイルが自動的に削除されることはありません。要するにこのままではデータベースの領域が増える一方なわけです。これが重さの原因です。


■公式で推奨されている方法:定期的に"Move Old Data to Archive"を実行する
実はこれ全然役に立ちません。
なぜか?
このコマンドを実行すると何が行われるかって、先ほどのデータベースに
タスクAとBとCはArchiveしたからもう二度と表示しなくていいよ.zip
これが追加されるだけなんです。

・・・え、かえってデータベースのサイズ増えてね?


■本当に有効な方法:定期的に"Compact DataBase"を実行する
で、こっちが本命です。このコマンドを実行すると、操作内容を格納しているZIPファイルをすべて削除して、一つの新しい「現在の状態を表すZIPファイル」だけが存在するデータベースを作り直してくれます。効果は劇的で、たとえば私の場合は11.5MBあったデータベースファイルのサイズが25KBになりました。
問題はこのコマンド、実は「同期設定を行っている最中は実行できません」。この辺マニュアルや公式FAQに書いてなくて困りました。

ということで、いったん環境設定からiPhone等との同期を「OFF」にしてから再度"Compact DataBase"を実行すると良いです。


■対策3:余計なバックアップを作成しない
初期設定ではクライアントが終了するたびにデータベースのバックアップを取るようになっていますが、これを放置しているととんでもない量のバックアップファイルが作成されてしまうので、設定を適当に変更しておくと良いと思います。

2009年12月19日土曜日

Java 使いの人向け ActionScript3 のクラス仕様まとめ

仕事の都合でJavaからActionScript3(FlexじゃなくてFlash 10みたいです)に乗り換えることになったので、クラスの仕様に親しむためまとめを作ってみました。


■参考文献
http://www.tom.sfc.keio.ac.jp/~fjedi/wiki/index.php?%A5%AF%A5%E9%A5%B9%BC%FE%A4%EA%A4%CE%BB%C5%CD%CD%28ActionScript3%29
こちらのWikiに完璧にまとまっていますので、ぶっちゃけこのWikiを見ればすべて解決すると思います。


■大原則
迷ったらJavaと同じ。
以下のJavaと違う点に掲載のない事項はすべてJavaと同じ。多重継承が無くてinterfaceが用意されている点など。


■Javaと違う点
  1. package宣言は.NETやC++のように{}で囲む必要がある。{}で囲んだ中はJavaとほぼ同じ。publicクラスが一つしか持てない等。
    package {
        //以下javaと同じ
        import flash.text.TextField;
        public class Hogehoge extends TextField { /*...*/ }
    }
  2. package{}の外側にファイルローカルな関数や変数やクラスを宣言できる。この領域はpackage{}の内側でインポートしたクラスやメソッドが使えない。別途インポートし直す必要がある。
    package {
        import flash.text.TextField;
        public class Hogehoge extends TextField { /*...*/ }
    }
    // 別途インポートが必要
    import flash.text.TextField;
    var abesi:TextField = new TextField();
  3. dynamicクラスがある。
  4. abstractクラスやabstractメソッドが無い。
  5. その他、native, synchronized, transientなどが無い。
  6. namespaceがある。(が、正直使い道がよく分からない)
  7. enum型はない。
  8. コンストラクタにもfunctionを付ける必要がある。
  9. コンストラクタは必ずpublicになる。アクセス制御修飾子を指定しないとpublicとして扱われる。
  10. オーバーロードが一切使用できない。コンストラクタもオーバーロードできない。
  11. オーバーライドの際には必ずoverride修飾子を付ける必要がある。
  12. プロパティのgetter/setterを作るために特別な仕様がある(get修飾子, set修飾子)

その他、クラス以外の違いとして、
  1. String型が参照渡しではなく値渡し(プリミティブ扱いなので)
  2. 関数の引数にデフォルト引数が利用できる(オーバーロードの代わりに使う)
    function abesi(a:String="abesi", b:String="hidebu") { /*...*/ }
    abesi(); //自動的にデフォルト引数が使用されるのでこういう呼び出しが可能
  3. 関数の可変長引数の指定の仕方が異なる
    //Javaでは
    public void abesi(String... args) { /*...*/ }
    //AS3では
    public function abesi(...args) { /*...*/ }


■サンプル
以上を踏まえて、練習がてらにプレイスホルダー付きテキストフィールドクラスを作ってみました。

Javaではコンストラクタのオーバーロードが必要になったところ、AS3ではデフォルト引数のおかげですっきり書けました。やっぱりデフォルト引数はいいですね。あと試しにtextColorプロパティのsetterをオーバーライドしてみたのですが、そのせいでthis.textColor = 0x999999とすると意図しないタイミングでdefaultTextColorが書き換わってしまいはまりました。super.textColorとしてスーパークラスのsetterを呼びだすようにして回避。getter/setterのオーバーライドは強力ですが上手く使わないと混乱を招く諸刃の剣になりそうです。

iMovie 08 でニコニコ動画にアップロードするための動画をエンコードする設定まとめ

皆さんご存じニコニコ動画。Windows環境で動画を作ってアップするための情報はたくさんあるのですが、Mac環境用のネタが少ないので、メモしておきます。

参考にしたページは以下の通り。
http://d.hatena.ne.jp/KZE/20091106/p1

http://www.smilevideo.jp/static/www/help/#000562

http://nicowiki.com/encode.html


■環境編
Mac OS X 10.6.2 Snow Leopard
iMovie 08
QuickTime Player X (Snow Leopard付属)

iMovieは08を使用します。各所でお勧めされているiMovie HDであれば高性能でflvも扱えるらしいのですが、新しいソフトを入れて管理するのが面倒という理由により却下です。また、iMovie 09からは動画クリップごとの再生速度管理もできるらしいので、kskとかスローモーションの演出もできるためそっちのほうがお勧めです。

エンコの際にはQuickTimeを利用してエンコするため、一応QuickTimeのバージョンも載せておきました。たぶんLeopard付属のQuickTime Player 9とかでもうまくいくと思います。


■エンコ設定編
まず注意点として、私はプレミアム会員なので、以下の設定はプレミアム会員用に合わせています(ビットレート最大1000Kbps程度、ファイルサイズ最大100MB)。一般会員の方はビットレートを落とせばそのまま利用できるかと思います。

さて肝心の設定内容ですが、http://d.hatena.ne.jp/KZE/20091106/p1で解説されている内容とほとんど同じです。iMovie 08からはそのままflvを書き出すことができませんので、mpeg-4 H.264でエンコードします。具体的には以下の通り。
  1. メニューの「共有」から、「QuickTime を使用して書き出す」を選択する
    Cmd+Eの「ムービーを書き出す」では上手くエンコできませんので注意。
  2. 「書き出し」欄は「ムービーからMPEG-4」を選択する
    ここで「ムービーからQuickTimeムービー」を選択するとどんなに上手くエンコしてもニコ動側で再エンコされてしまいます。絶対に「ムービーからMPEG-4」を選択すること。
  3. 以下の画像のように設定する



    一番上のファイルフォーマットを「MP4(ISMA)」から「MP4」にしないとH.264でエンコできませんので、まず最初に変えておくこと。
    一般会員の方はムービーのデータレートをもっと落としてください。300ぐらいかな?逆に600より上げる必要はよっぽど画質が気になるか短い動画でもないかぎり無いと思います。ビットレートについては私なんぞよりもまとめWikiなどのほうが詳しいのでそちらをご覧ください。
  4. 「ストリーミング」の「ストリーミングを使用する」チェックボックスは入れない
    入れても大丈夫かどうかは未確認ですが、余計な物を入れると変なことになるのではと思い外してます。入れた方がいいのかな・・・

■仕上がり編
上記の設定でエンコしてみた結果がこちら。


特に問題なく見られていると思います。ただしエコノミー回避はしていないのでエコノミーが発動すると悲惨なことになりそうですが・・・


■FLVでエンコしたい編
FLVでエンコしたい場合や、もっと詳細な設定がしたい場合には、ffmpegXというツールを使うと良いようです。試していないのでここでは割愛します。
その他、iMovieから直接FLVでエンコできるようにする方法もあるらしいです。しかしH.264で直接アップロードできるようになった今となっては別にFLVにこだわるメリットも無いかも。

2009年12月16日水曜日

bulkloader.py を使って Google App Engine の本番サーバーから開発サーバーにデータを移す

Google App Engine SDKの開発サーバーのデータストアはtmpディレクトリにデータを保存するため、マシンを再起動するとデータの中身が全部消えてしまいます。毎回テストデータを用意するのが面倒なので、本番サーバーからデータを移してくるための方法を調べてみました。するとbulkloader.pyというユーティリティを使うと、簡単に本番サーバーのデータをダウンロードして保存し後からリストアすることができることがわかりました。ということで早速試してみます。
参考にしたのは以下のサイト。
http://code.google.com/intl/en/appengine/docs/python/tools/uploadingdata.html

※2010/01/31追記:--db_filenameオプションの使い方を掲載しました。


■前準備
app.yamlに以下の設定を追加してから、appcfg.py updateで本番デプロイを行います。
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
これだけで準備ばっちりです。余談ですが、app-engine-patchを使うと、最初からこの設定がapp.yamlに含まれています。


■使用方法
本番サーバーからローカルにデータをダンプするときは以下のコマンドを実行します。
bulkloader.py --dump --kind=<kind> --url=http://<appname>.appspot.com/remote_api --filename=<data-filename>
たとえば私のアプリからhon_heroという名前のModelのデータをダンプしたいときには、
bulkloader.py --dump --kind=hon_hero --url=http://akisutesama.appspot.com/remote_api --filename=hon_hero.dump
などとするとうまくいきます。

ダンプしたデータを本番サーバーにリストアするときは以下のコマンドを実行します。
bulkloader.py --restore --kind=<kind> --url=http://<appname>.appspot.com/remote_api --filename=<data-filename>
--dumpが--restoreになっただけです。本番障害でデータが失われたときにリストアするためのコマンドなので、実行すると本番サーバーのデータがすべてダンプした地点のデータに置き換えられます。ご利用の際には細心の注意を!

ダンプしたデータをローカルサーバーに入れるときは以下のコマンドを実行します。
bulkloader.py --restore --kind=<kind> --url=http://localhost:8080/remote_api --filename=<data-filename> --app_id=<appname>
本番だけではなくてローカルサーバーにもリストアができます。ローカルサーバーにリストアする際の注意点として、
  • dev_appserver.pyでアプリケーションが動いている必要があります。
  • --urlオプションをローカルホストに書き直す必要があります。
  • --app_idオプションで、自分のアプリケーションのapp_idを指定してやる必要があります。
これでローカルテストがだいぶ楽になりました。

同様にして、本番からデータをダンプしてローカルに入れるだけでなく、ローカルからデータをダンプして本番に入れることもできます。新しく実装した箇所に最初からデータを入れたい場合などに使えると思います。


■log, progress, resultを賢く使う
bulkloader.pyを実行すると、デフォルトでは以下のような名前のファイルが自動的に生成されると思います。
bulkloader-log-20091211_145622.log
bulkloader-progress-20091211_145622.sql3
bulkloader-result-20091211_145622.sql3
これらはそれぞれ「ログファイル」「現在どのエンティティまでダンプされたかを格納するデータベース」「実際にダンプした内容を格納するデータベース」となっており、上手く使えば2回目以降のダンプ実行時間を劇的に短くすることができます。

ログファイルを指定する際には--log_fileオプションを、データベースを指定する際には--db_filenameと--result_db_filenameを、それぞれ指定してください。たとえば、以下のようなシェルスクリプトを用意しておくと便利です。
#!/bin/sh

# 前回の実行結果が残っているとエラーになる(上書きしてくれない)ので、まずいったん消す
if [ -e hon_hero.dump ]; then
rm hon_hero.dump
fi
# bulkloader.pyを実行する
# db_filenameとresult_db_filenameは一緒のファイルを指定してもかまいません。
# (その場合は、一つのsqlite3データベースに一緒に格納されます)
# db_filenameとresult_db_filenameは、db_fileやresult_db_fileのように短縮して書いても動作するみたいです
bulkloader.py --dump \
--url=http://akisutesama.appspot.com/remote_api \
--kind=hon_hero \
--filename=hon_hero.dump \
--log_file=bulkloader-log-hon_hero.log \
--db_file=bulkloader-progress-hon_hero.sql3 \
--result_db_file=bulkloader-progress-hon_hero.sql3
こうすることで、2回目以降はbulkloader-progress-hon_hero.sql3の中身とリモートのdatastoreの中身を比較して、追加更新のあったもののみをダウンロードし、それ以外はローカルに保存してあるデータベースの中身を利用するので、劇的に処理が速くなります。結果はこちら。
[INFO    ] Connecting to akisutesama.appspot.com/remote_api

[INFO ] Have 2610 entities, 2610 previously transferred
[INFO ] 2610 entities (974 bytes) transferred in 0.4 seconds
1回目のロードには130秒かかったのですが、2回目はすべてローカルに保存されているデータを使ったので、なんと0.4秒で済んでいます。

こうしてダンプしたデータをローカルサーバーでリストアするときは、たとえば以下のようなシェルスクリプトを使います。
#!/bin/sh

# --db_fileと--result_db_fileには先ほどのダンプ時に指定したものとは別のファイルが必要になります
# (先ほどのデータベースはappspot.com用として設定されるので、localhostで使用するとエラーになってしまいます)
# --db_fileと--result_db_fileには特別な名前としてskipを指定することができます
# この名前を使用するとデータベースへの書き込み/読み込みを行いません
bulkloader.py --restore \
--url=http://localhost:8000/remote_api \
--app_id=akisutesama \
--kind=hon_hero \
--filename=hon_hero.dump \
--log_file=bulkloader-log-restore.log \
--db_file=skip \
--result_db_file=skip


■注意点
appspot.com以外のサーバー(たとえばlocalhostなど)からデータをdumpしたりrestoreしたりする際には、必ず--app_idオプションを指定する必要があります。これを忘れていて詰まりました><

もし特定の条件を満たすデータのみをダウンロードしたいという場合などは、設定ファイルをPythonで書く必要がありますが、appcfg.py download_dataを使うと良いと思います。

2009年12月13日日曜日

Highcharts.js を使ってみた


最近IDEA*IDEAさんで取り上げられていたHighcharts.jsを試してみましたので、躓いた点などをメモしておきます。


■公式サイト
http://www.highcharts.com/
ダウンロード、更新履歴はこちらから見られます。ライセンスもこちらに記載があります。
個人利用、教育目的の利用、および非営利組織での利用については無料ですが、商用利用の際にはライセンスの購入(1サイト$80、複数サイト$360)が必要になるので注意です。


■公式リファレンス
http://www.highcharts.com/ref/
おそらく全部JSで実装されているのだと思いますが、凄いクオリティ高いです・・・


■実際に導入してみて躓いたポイント
以下、すべてバージョン1.0.2(2009/12/09)での気づきです。
グラフを描画する領域のサイズは、CSSでは定義できない、直接style属性に書く必要がある
たとえばCSSを使って、
<style>#chart_area {width:800px; height:400px;}</style>
<div id="chart_area" ></div>
のようにしても描画時に無視され、高さが0になります。必ず直接style属性を用いて
<div id="chart_area" style="width:800px; height:400px;"></div>
のように書く必要があります。

Zoom機能を使う際、画面のスクロールが発生すると選択領域がバグる
Mac OS X 10.6上のFirefox3.5.6とSafari4.0.4にて再現。他のブラウザは未チェックです。論より証拠、こちらのページを開いて、少し画面全体を下にスクロールしてから、チャートを縦にドラッグしてY軸ズームしようとしてみてください。まぁ、ひどいバグなのですぐに直るとは思いますが。

seriesに与えるデータは、必ずX軸方向の昇順にソートされている必要がある
特にxAxisにdatetimeを指定しているときが危険です。たとえばこのようなデータはNGです。
series: [{
name: 'Plague Rider',
data: [[Date.UTC(2009, 12, 4), 57.4],
[Date.UTC(2009, 12, 3), 57.6],
[Date.UTC(2009, 12, 2), 59.1]]
}]
かならずこのようにソートしなければなりません。
series: [{
name: 'Plague Rider',
data: [[Date.UTC(2009, 12, 2), 59.1],
[Date.UTC(2009, 12, 3), 57.6],
[Date.UTC(2009, 12, 4), 57.4]]
}]
ソートされていないと、チャートにマウスカーソルを合わせてもラベルが表示されなくなります。気づきにくいバグでした。

seriesに与えるデータにnullがあると、0として扱われる
そのため、たとえば12月1日は100、12月2日は110、12月3日はデータが分からないのでnull・・・とすると、12月3日のところだけいきなり0になってグラフが滅茶苦茶になります。回避方法としてはxAxisのtypeをdatetimeにするか、yAxisのminを自分で計算して指定してください。

xAxisのtypeがdatetimeのとき、連続していないデータがあるとsplineは使用できない(lineは使用できる)
原因は不明です。たぶんバグじゃないだろうかと思ってますが、公式のxAxisのtypeがdatetimeなサンプルを見てもsplineではなくてlineを使っているのでひょっとしたら仕様かもしれません。

■まとめ
公開されたのがつい先月の末ということで、まだちょっとBuggyな感じです。また、エラーメッセージがまともに表示されないため、JSファイルのどこでエラーになっているかはわかっても原因が何か分からないなど、デバッグが結構大変です。しかしながらデザイン美麗で機能豊富、カスタマイズも容易と、一通り優れた点は持ち合わせていると思います。PrototypeやjQueryなど他の外部ライブラリに依存しないのも良い点です。$80なら支払ってもよいのでは?


■Google Charts APIとの比較
やはり気になるのはGoogle Charts APIと比べてどちらが使えるかでしょう。ちょっと調べてみました。ただしGoogle Charts APIについては実際に試したことがないのであくまで公式ページのドキュメントを見て気づいた点のみです。間違っていたらごめんなさい。
Highcharts.jsの優れている点
  • 美麗なデザイン
  • ズームや特定データの一時消去、ラベル表示など、対話性に優れたUI
  • 単体のJSファイルなので外部のサーバに依存しない
  • Ajax対応が容易

Google Charts APIの優れている点
  • より多数のグラフに対応(レーダーチャートや地図など)
  • 商用利用でも完全に無料

2009年12月11日金曜日

Django の Template Filter には任意の変数を使用することができる

公式ドキュメントに記載がなかったので、自分用メモ。

たとえばDjangoのフィルターで、
{{ some_value|floatformat:1 }}
としているところを、viewから変数を渡して
{{ some_value|floatformat:floatpoint }}
のように書くことができます。他にも
{{ now "%Y %m %d" }}
{{ now date_format }}
みたいに書くとか。・・・常識?

Heroes of Newerth の統計情報を集めるサイトにグラフを付けてみた



前回に引き続きおしらせです。
HoN統計情報サイトに、今度は時系列の折れ線グラフを付けてみました。


■追加した機能
今のところ、以下の3種類の統計をグラフで見ることができます。
  • Usage Percent(ヒーロー使用率、高いほうが人気があります)
  • Winning Percent(勝利率、高いほうが強いです)
  • K/D ratio(Kill/Deathレシオ、高いほうが俺Tueeできます)

グラフに表示されるのはトップ10までです。11位以下のヒーローにつきましては現在ページングして見られるように対応を進めてますので少々お待ちください><


■日本語化?
すみません、(主に作者の怠慢が理由ですが)英語版しかありません・・・でも数字ばっかりなのでたぶん大丈夫です!

2009年12月1日火曜日

Heroes of Newerth の統計情報を集めるサイトをつくってみた



ということで、作ってみました。

■そもそもHeroes of Newerthって何?
http://wikiwiki.jp/hon/
βキーが一つ余ってますので先着一名で差し上げます(コメントなりTwitter Dなりください><)


■何これ?
http://www.heroesofnewerth.com/heroes.phpあたりからデータを抜いてきて蓄積し、現在どのヒーローが一番使われているか、どのヒーローが一番勝率がいいか、等を一覧表示しています。

デフォルトのソート順序はUsage %(使用率)です。テーブルのヘッダをクリックするとソート順序を変更することができます。1回クリックで昇順、2回クリックで降順です(たぶん)。

データは1日1回アメリカ西海岸時間の朝9時半ぐらいに更新するようにしています。日本だと深夜1時ぐらいかな。朝起きたらちょうど良く変わっていると思います。

あ、あとspan機能はいま動きません。あのセレクトボックスを選択しても何も起きません。あしからず><


■で、どうするの?
Opheliaたんが余りにも使われていないのを見て嘆き悲しむといいと思います。


■今後
時系列での変化を見られるようにしたいですね。パッチが当たってScout使用率減って涙目とか、Maliken先生勝率アップとか見てみたいです。

Processingはじめました


こんにちは。いろいろ始めすぎて終わってるakisuteです。
今更ですが、積ん読していたビジュアライジング・データを読み始めたので、Processingに手を出してみました。

4873113784ビジュアライジング・データ ―Processingによる情報視覚化手法
増井 俊之 (監訳)
オライリージャパン 2008-12-01

by G-Tools


楽です。とにかく楽です。文法は慣れ親しんでいるJavaですし、グラフィックを描画する以外の一切余計な機能がありません。そして、グラフィックを描画するために必要な機能は一通りあります。まさに、どうやってコンピュータにグラフィックを書かせるか、どうやってアニメーションさせるかを学ぶのに最適の環境じゃないでしょうか、これ。

たとえばこんな感じの弾幕が、


たったのこれだけのソースで動きます。すばらしい。
http://gist.github.com/246029

Processingももちろん素晴らしいですが、ビジュアライジング・データの内容そのものも素晴らしいです!

Google App Engine SDK の dev_appserver.py が自動的に index.yaml を更新してくれない時の対処法

ときどきGoogle App Engine SDKのdev_appserver.pyが自動的にindex.yamlを更新してくれない時があるので、原因を調べてみました。


■いきなりネタバレ
犯人は改行文字


■前提条件
index.yamlは、以下の様な作りになっています。
indexes:

- kind: django_admin_log #手動で定義したインデックス
properties:
- name: content_type
- name: object_id
- name: action_time

# AUTOGENERATED

# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run. If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED"). If you want to manage some indexes
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.

- kind: hon_herostatistics #ここから下は、自動的にdev_appserver.pyが追加してくれるindex
properties:
- name: fetchCompleted
- name: hid
- name: datetimeCreate
direction: desc
このように、# AUTOGENERATEDコメントが存在すれば、その下に自動的に必要なindexを生成してくれるようになっているのですが、時々この自動生成がうまくいかない場合があります。


■症状
具体的には、以下のように余計な物をすべて消した状態のindex.yamlを用意しても、dev_appserver.pyが「indexが手動定義されているので、自動生成しないよ」とエラーを吐きます。
indexes:

# AUTOGENERATED
困りました。


■原因と対処
そこでよくよく調べてみるためにvimではないエディタでこのindex.yamlを開いてみたのですが、すると末尾の改行文字がCRLF(dos形式)になっていました。そこで私のMacの環境に合わせて改行文字をLF(unix形式)にしてみたところ、無事にdev_appserver.pyのindex自動生成が動作するようになりました。vimで操作するなら、
:set fileformat=unix
とすればよいです。