先週の金曜の深夜に何故かひらめいてpythonはじめたとき放置してたGAEjの方をアップしておきます。

% sudo port install jruby
% sudo gem install google-appengine
% mkdir hello-gae-sinatra-dm-haml
% cd hello-gae-sinatra-dm-haml
必要なファイル・ディレクトリを自動作成しつつ各種gemを入れます。(カレントディレクトリの.gem以下に入る)
% appcfg.rb gem install sinatra dm-appengine addressable extlib haml
% vi config.ru 
require 'appengine-rack'
AppEngine::Rack.configure_app(
  :application => 'application-id',
  :version => 1)
require 'application'
run Sinatra::Application
% vi application.rb
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'haml'
require 'sass'

DataMapper.setup(:default, "appengine://auto")

class Post
  include DataMapper::Resource

  property :id, Serial
  property :body, Text
end

helpers do
  include Rack::Utils
  alias_method :h, :escape_html
end

get '/' do
  @posts = Post.all
  haml :index
end

post '/' do
  post = Post.create(params[:post])
  redirect '/'
end

get '/stylesheet.css' do
  content_type 'text/css', :charset => 'utf-8'
  sass :stylesheet
end

DataMapperパターンはActiveRecordパターンより抽象度が高いのでadapterさえあればKVSにも対応可能。凄いですね。

% mkdir views
% vi views/index.haml 
!!! XML
!!!
%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "ja", :lang => "ja"}
  %head
    %title Guestbook using GAEj Sinatra DataMapper Haml
    %link{:href => "/stylesheet.css", :rel => "stylesheet", :type => "text/css", :media => "screen"}
  %body
    %form{:action => "/", :method => "post"}
      %input{:type => "text", :name => "post[body]"}
      %input{:type => "submit"}
    %ul
      - @posts.each do |post|
        %li
          = post.body
% vi views/stylesheet.sass
body
  :font
    :size 42px

最終的なディレクトリ構成はこんな感じ。

% tree
.
|-- WEB-INF
|   |-- appengine-generated
|   |   |-- build_status.yaml
|   |   |-- datastore-indexes-auto.xml
|   |   `-- local_db.bin
|   |-- appengine-web.xml
|   |-- lib
|   |   |-- appengine-api-1.0-sdk-1.2.5.jar
|   |   |-- appengine-jruby-0.0.4.jar
|   |   |-- appengine-jruby-rubygems-0.0.4.jar
|   |   |-- gems.jar
|   |   `-- jruby-rack-0.9.5.jar
|   `-- web.xml
|-- application.rb
|-- config.ru
|-- public
`-- views
    |-- index.haml
    `-- stylesheet.sass

必要なファイルは殆ど自動生成(or コピー)してくれてます。

% dev_appserver.rb .
Guestbook using GAEj Sinatra DataMapper Haml

日本語が文字化けるのは謎。

Start - Bottle Web Framework

Powered by Google App Engine

% mkdir hello-gae-bottle
% cd hello-gae-bottle
% cp /opt/local/lib/python2.5/site-packages/bottle.py .

Bottleは1ファイルなんですね。素敵です。

% vi hello.py
from bottle import route, default_app
from google.appengine.ext.webapp.util import run_wsgi_app

@route('/')
def index():
    return 'Hello, GAE Bottle!'

run_wsgi_app(default_app())

webappに含まれてるrun_wsgi_appを使うところ以外は普通のwsgiアプリですね。

% vi app.yaml 
application: hello-gae-bottle
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: hello.py

CGIの時と同じ。

% dev_appserver.py .
http://localhost:8080/

やはりpythonでやると一番手っ取り早いですね。

Powered by Google App Engine

ダウンロード - Google App Engine - Google CodeからGoogleAppEngineLauncher-1.2.7.dmgをダウンロードしてインストール。

dev_appserver.pyとappcfg.pyコマンドも入ります。GAEjと同じ名前ですね。

% mkdir hello-gae-python
% cd hello-gae-python
% vi hello.py
print "Content-Type: text/plain"
print ""
print "Hello, GAE Python!"

普通のCGIですね。

% vi app.yaml
application: hello-gae-python
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: hello.py

GAEjのappengine-web.xmlとweb.xmlを一つにした感じですね。

% dev_appserver.py .
http://localhost:8080/

うん。やっぱりGAEjよりだいぶ楽ですね。

Start - Bottle Web Framework

昨日の調べで良さそうだったBottleというWAFを使ってみました。

単独で起動

% sudo pip install bottle
% vi hello.py
from bottle import route, run

@route('/')
def index():
    return 'Hello Bottle!'

run(host='localhost', port=8080)

デコレータでroutingするところが素敵。(routingと処理が別々の場所にあるのは面倒)

% python hello.py 
Bottle server starting up (using WSGIRefServer (localhost:8080))...
Listening on http://localhost:8080/
Use Ctrl-C to quit.
http://localhost:8080/

mod_wsgiで起動

% sudo vi /opt/local/apache2/conf/extra/httpd-vhosts.conf
(...)
<VirtualHost *:80>
    ServerName hello-bottle
    DocumentRoot "/Users/komagata/Sites/hello-bottle"
    WSGIDaemonProcess hello-bottle processes=2 threads=15
    WSGIScriptAlias / /Users/komagata/Sites/hello-bottle/app.wsgi
</VirtualHost>

mod_wsgi起動の場合はちょっと違う。applicationにclassだか関数だけを入れとけば実行してくれるって感じかな?(勘)

from bottle import route, default_app

@route('/')
def index():
    return 'Hello, Bottle! on mod_wsgi'

application = default_app()
http://hello-bottle/

django(1日だけのハンズオンセミナーでちょっと触った)、TruboGears(本読んだ)、web.py(何となく眺めた)、Pylons(触れてない)という程度の調べだけど、このBottleに抜群に好感触を得ました。(要はSinatraに似てるからなんだけど)

PyPI(Python Package Index) == rubyforge, setuptools == rubygems, easy_install == gemという理解でいいのかな?

% sudo port install py25-setuptools
% sudo easy_install SQLAlchemy

と思ったら・・・

% port search easy_install
py-pip @0.4 (python, www)
    An easy_install replacement

py25-pip @0.4 (python, www)
    An easy_install replacement

py26-pip @0.4 (python, www)
    An easy_install replacement

pip == gemという感じ?

% sudo port install py25-pip
% sudo pip install GHRML

という訳でもないみたい。

genshiって何?コンパイルはじまっとる!search的なものは無いのかな?など疑問は増えつつインストール完了。

% port variants mod_wsgi
mod_wsgi has the variants:
   python24: Use Python 2.4
     * conflicts with python25 python26 python31
   python25: Use Python 2.5
     * conflicts with python24 python26 python31
[+]python26: Use Python 2.6
     * conflicts with python24 python25 python31
   python31: Use Python 3.1
     * conflicts with python24 python25 python26
   universal: Build for multiple architectures
% sudo port install mod_wsgi +python25

passengerと同じ感じで設定。

% sudo vi /opt/local/apache2/conf/httpd.conf
(...)
# mod_passenger
Include conf/extra/httpd-passenger.conf

# mod_wsgi
Include conf/extra/httpd-wsgi.conf
(...)
% sudo vi /opt/local/apache2/conf/extra/httpd-wsgi.conf
LoadModule wsgi_module modules/mod_wsgi.so
WSGIPythonHome  /opt/local

何も書かないとmod_wsgi含むapacheプロセスが立ち上がって勿体無いのでpassengerと同じ様に単独で立ち上がってsocket通信するDaemon modeというので起動。

% sudo vi /opt/local/apache2/conf/extra/httpd-vhosts.conf
(...)
<VirtualHost *:80>
    ServerName hello-mod-wsgi
    DocumentRoot "/Users/komagata/Sites/hello-mod-wsgi"
    WSGIDaemonProcess hello-mod-wsgi processes=2 threads=15
    WSGIScriptAlias / /Users/komagata/Sites/hello-mod-wsgi/hello.wsgi
</VirtualHost>
% sudo vi /etc/hosts
(...)
127.0.0.1       hello-mod-wsgi
(...) 
% vi ~/Sites/hello-mod-wsgi/hello.wsgi
def application(environ, start_response):
    start_response('200 OK', [('Content-type', 'text/plain')])
    return 'Hello, mod_wsgi!'
% sudo /opt/local/apache2/bin/apachectl restart

特に指定しないとlogsディレクトリにapacheの権限で立ち上がるみたいです。

% ls -l /opt/local/apache2/logs/*.sock  
srwx------  1 _www  admin  0 10 27 00:45 /opt/local/apache2/logs/wsgi.815.4.1.sock
http://hello-mod-wsgi/

なるほど

iPhone買ったらPC用のネット環境が無くなったのでE-MOBILEのW31DH買いました。金が無くなっていく・・・。

でもMacBook自体結構バッテリー持つのでどこでも繋がるのはやはり便利ですね。

EMOBILE D31DW

ジョナサンアイブが見たら即座に銃のセーフティーロックを解除しそうです。

PythonのWAFやORMやテンプレートエンジンにはどういうのがあるのか調べてみました。

俺の要望

  • GAEでも使えるものがいい。
  • 複雑なRoutesはうんざり。シンプルなのがいい。
  • ActiveRecordはうんざり。DataMapperがいい。
  • hamlみたいにインデントを綺麗に出してくれるテンプレがいい。
  • layoutみたいにパーツでなく枠を共有できるテンプレがいい。

調べた感じ

  • GAE SDKにdjangoが入ってるらしい。
  • Routingは正規表現が多い。
  • SQLAlchemyというORMがDataMapperパターンらしい。
  • インデントをそろえてくれるテンプレがみつからない。
  • 枠の共有はテンプレの継承で行うみたい。(?)
  • web.pyというのがシンプルっぽい。

「PythonでWAF,ORM,テンプレつったらxxxだろうjk・・・」

「xxx知らない情弱は負け組」

というのがあれば教えて頂けるとうれしいです。

python2.5からwsgirefというモジュールが標準で入ってるそうです。WSGIのリファレンス実装って意味かな?Rubyで言えばRackとWEBrickが標準で入ってるって感じでしょうか。

% vi wsgi.py
def application(environ, start_response):
  start_response('200 OK', [('Content-type', 'text/plain')])
  return 'Hello, WSGI!'

from wsgiref import simple_server

if __name__ == '__main__':
  server = simple_server.make_server('', 8080, application)
  server.serve_forever()
% python wsgi.py
http://localhost:8080/

ほう。

インストール。GAEがpython2.5だそうなので2.5を入れてみた。

% sudo port install python25
(...)
To fully complete your installation and make python 2.5 the default, please run
        sudo port install python_select
        sudo python_select python25

python_selectを入れて実行せよと出た。debianのupdate-alternativeみたいなもんだろう。

% sudo port install python_select
% sudo python_select -s
python26-apple
% sudo python_select python25
% sudo python_select -s
python25

macのデフォルトは2.6なんですね。これが普通なのかわからないけど2.5にしておきました。

% vi hello.py
print "Hello, Python!"
% python hello.py 
Hello, Python!

うん。