blog.snaka.info
(ただし、Homebrewer に限る)
$ brew install reattach-to-user-namespace --wrap-pbcopy-and-pbpaste
でいけます。
下のリンクの記事読んで、「ああ、なんか面倒くさそう…もしかして… 」と、思ったら Homebrew でインストールできるようになってました。便利な世の中になりました。
> I’m trying to create an extension like Django template tags forWhy do you need an extension for that? A function is perfectly fine:
> jinja2. the basic idea is a tag in the main template( {% widget
> last_tweets %} ) that return a node of a source taked from another
> file ( widgets/last_tweets.html for example ).
Jinja2 template tags extension like Django - pocoo-libs | Google グループ
らしいです。
ちなみに、動作環境は GAE です。
まず、main.py を書く
7行目で、env.globals['hoge'] = lambda: u"ほげほげ"というように関数オブジェクトをglobalsというアトリビュートに'hoge'という名前で格納しているのがミソ。
で、テンプレートの記述は以下のようになる。
ここでは、hoge()のように、前述のglobalsに格納した名前で関数を呼び出す。すると…

となる。
ほんと、楽チンですね。
ちゃんとしたタグを作りたいなら、以下を参考にしたらいいみたい(まだ作ったことない)
でも、
Jinja extensions work ahead of time. They emit nodes from an abstract
syntax tree which are then used to generate sourcecode. This is usually
a very complex topic and only recommended if functions no longer work
which are a lot easier to implement and way easier to debug.
と言ってるように、この程度の用途ならデバッグしやすさとかを考慮しても関数を使うほうが楽でいいみたい。
ほとんど自分向けのメモ
なんか、いつのまにかAppEngineのデフォルトがPython2.7になっちゃてて、公式には日本語チュートリアルがほとんど無いので書いとく。
まず、3行目の runtime: python27で Python 2.7 を使うようになる。
それと、threadsafe: yesは「このアプリケーションはスレッドセーフなので、ばんばんマルチスレッドでリクエスト飛ばしててねー」という意味。逆に「スレッドセーフって何?」って感じなら、noにしておく。
Python 2.7 にした場合、このthreadsafeの指定は必須となるので注意。
つぎに9行目。script: main.appが今までと違っている。いままでは、main.pyっていう感じでスクリプトファイル名だったのが、WSGIApplicationが実装されているモジュールと、そのインスタンスが格納されている変数名という感じに変っている。
これは、いままでCGIとして動作していたのがネイティブなWSGIアプリケーションとして動作するようになったためらしい。
また、11行目以降の、librariesで、使用するフレームワークやテンプレートエンジンの名前とそのバージョンを指定する必要がある。
「べつにバージョンとか知らねーし?新しいのでいいしょー」って場合は、latestって書いておけば今のSDKで用意しているバージョンの最新が使われる。
ここの変更点は、3,4行目で importするモジュールが、いままで、google.appengine.webapp とか、google.appengine.webapp.templateだったものが、webapp2やjinja2になった。
そして、6-8行目は Jinja2 でテンプレートを読み込むために必要な準備として、テンプレートが格納されている場所をLoaderに教えてあげているところ。
このように記述すると、main.pyが格納されているのと同じ場所からテンプレートを読み込んでくれる。
12行目でEnvironmentクラスのget_templateメソッドでテンプレートを取得して。
13行目でTemplateクラスのrenderメソッドでテンプレートをレンダリングしている。
テンプレートの書き方自体は Diango のテンプレートの書き方とほとんど一緒。
その他に気をつけるべき点が掲載されていたのでのせておく。参照すべきリンクは原文:「Using Python 2.7 - Google App Engine — Google Developers」を参照。
app.yamlでthreadsafeを有効にして、フロントエンドのインスタンスを増やすことができる。Crypto.Util.randpoolは非推奨となったので、Crypto.Randomを使う。
もう約2週間ほど前になるが、大友克洋GENGA展にいってきた。
場所は秋葉原と御徒町の間くらいにある、3331 Arts Chiyoda というところ。 元が学校だったみたいで、最初、Google Map 頼りにその場所についたら学校そのものだったので場所を間違えたと思って不安になってしまった。
表にまわれば、大々的にやってたので安心したが。

予約の開場時間の16時より早めについたので、近くのカフェで時間調整。アイスカフェラテを頼んだが、オープンな感じの場所で肌寒かったのでちょっと後悔した。
と、しばらくしてやっと開場時間がきたので、もういちど開場へ。
展示内容は、大まかにAKIRAの表紙絵や映画ポスター、カメラの広告やヴォルビックなどの広告用のポスターおよび、これまで手がけたマンガ原稿の一部が展示されているスペースと、AKIRAの生原稿全てという感じになっている。
というか、展示スペースの4分の3以上はAKIRAな感じになっていたと思う。
つい、最初から最後までストーリーを追っかけながら見てしまった。
ギャラリーの最後には、冒頭の金田のバイクがあったり、童夢の壁を再現しているスペースで自由に記念撮影ができるスペースとなっていた。

そこの壁1面は自由に落書きできるようになっていて、中には有名なマンガ家の落書きもいっぱいあった。




カスタムテンプレートタグ(長いので以下’カスタムタグ’と呼ぶ)やフィルタの作り方は、基本的にはDjangoのそれと同じようだが、それを使うための作法がちょっと違うので注意が必要です。
Djangoのカスタムタグに関する情報は「テンプレートタグやフィルタを自作する — Django v1.0 documentation」を参照。
たとえば、単純に”Hello GAE world”と出力するだけの簡単なカスタムタグを作ってみる。 するとコードは以下のような感じになる。
このときの注意が2つある。
1つ目は、registerという名前は固定であること。
このあと掲載するmain.py(テンプレートをレンダリングする側)のコードでカスタムタグをDjangoのテンプレートシステムにモジュールを登録するが、そのときモジュール内のregisterを探してそれを登録する仕組みになっているのがその理由。
2つ目は、このファイルの格納場所に関するもの。
モジュールとして読み込まれるため、Pythonの作法に従って、このファイルを格納するためのディレクトリを作成し、そこに__init__.pyを用意したうえで、このファイルをそこに格納する必要がある。
__init__.py が無い場合、’ImportError: No module named tag_library‘となる。
上記のように、タグを定義したモジュールのことを Django のテンプレートシステムでは「ライブラリ」と呼んでいるみたいです。
カスタムタグを利用するには、あらかじめ前述の手順で作成したライブラリをDjangoのテンプレートシステムに登録してあげる必要があります。 カスタムタグを利用する側(テンプレートをレンダリングする側)のコードは以下のような感じになります。
冒頭で、template.register_template_library('tag_library.my_tags')と記述している箇所が、ライブラリを登録している箇所になります。
これで、Djangoのテンプレートシステムに'my_tags.py'が読み込まれ、その中に記述されているタグを定義した関数'hello'がカスタムタグとして登録されます。
さっそくカスタムタグをテンプレート本体に組み込んでみます。 以下のような感じになります。(簡単のためDOCTYPEとかいろいろ省いています)
ここでも1つ注意が。
Djangoでカスタムタグを使用する場合は、{% load %}タグで使用するカスタムタグライブラリを読み込む必要がありますが、GAEの場合は、前述のmain.pyでregister_template_libraryしているので、 {% load %}は不要であることです。
で、これを実行すると。

のようになります。 GAE/Python(というかDjangoか)まだまだ勉強中ですが奥が深いですね。
次回は、「GAE/Pythonでテスト駆動開発するための環境を作る」の予定です。
最終的にはコンパイラを作ってみたいと考えて、ANTLRとLLVMを勉強中。
ANTLRはJavaで実装されたパーサジェネレータ。 ANTLRの使い方がなんとなく分かったので、Brainf*ckのインタプリタを実装してみた。 ANTLRによるインタプリタの作り方については別記事で投稿する(かも)。
とりあえず、コードを晒しておく
上記のコードをBF.gという名前で保存して(名前は重要!)、以下のよう ANTLR にパーサのソースコードを生成させる。
$ antlr BF.g
すると、カレントディレクトリに BFParser.java, BFLexer.javaが出来ているので、
$ javac BFParser.java BFLexer.java
でコンパイル
無事インタプリタがコンパイルできたら、”Hello world”を実行してみる。
$ java BFParser
と実行すると、インタプリタがコマンドの入力待ちの状態になるので、以下のコードをコピペして、最後にCtrl+dで入力を終了する。
>+++++++++[<++++++++>-]<.
>+++++++[<++++>-]<+.
+++++++.
.
+++.
[-]>++++++++[<++ ++>-]<.
>+++++++++++[<+++++>-]<.
>++++++++[<+++>-]<.
+++.
------.
--------.
[-]>++++++++[<++++>-]<+.
[-]++++++++++.
※上記コードはBrainf*ckより拝借。 これで、”Hello World!” が表示されればOK
$ java BFParser
>+++++++++[<++++++++>-]<.
>+++++++[<++++>-]<+.
+++++++.
.
+++.
[-]>++++++++[<++ ++>-]<.
>+++++++++++[<+++++>-]<.
>++++++++[<+++>-]<.
+++.
------.
--------.
[-]>++++++++[<++++>-]<+.
[-]++++++++++.
Hello World!