2012 Pythonアドベントカレンダー 18日目 PasteDeployを知ってるかい?

From Evernote:

2012 Pythonアドベントカレンダー 18日目 PasteDeployを知ってるかい?

PasteDeployを知ってるかい?

さて、2012 Pythonアドベントカレンダーの18日目です。

一応Webフレームワークに関連してればよいということで、普段あまり言及されないPasteDeployの話をしておきます。

PasteDeployとは?
ああ、プロジェクトのテンプレートを展開するやつですよね?とかしたり顔で聞いてくる奴は自分で穴掘ってもぐっといてください。
PasteScriptのpaster createのことではありません。
paster serveのほうです。

PasteDeployは、iniファイルでWSGIアプリケーションやミドルウェア、サーバーの設定や構成を管理するものです。
で、そのiniファイルを paster serveに渡せば WSGIアプリケーションが実行されるわけですね。

WSGIがわからない人は、 http://shomah4a.bitbucket.org/advent_calendar/2012/wsgi.html を読んでね。

ちょっとだけWebOb
まあ、とりあえずHelloなWSGIアプリケーションでも作って動かしてみましょう。

helloapp.py

from webob.dec import wsgify

@wsgify
def hello(request):
    return u"Hello, world!"

shomah4a の例と違うのはWebOb使ってるところ。

ではこれを動かすので、 webob と pastescriptをインストールしましょう。

$ pip install webob pastescript

pasterコマンドが使えるようになりますが、これでいきなりWSGIアプリケーションを動かせるわけではありません。
WSGIアプリ、ミドルウェア、サーバーの構成を定義する ini ファイルが必要です。

PasteDeployしてみよう
ひとまず最少の構成では、WSGIアプリとサーバーを指定すればOKです。

hello.ini

[app:main]
paste.app_factory = helloapp:main

[server:main]
use = egg:paste#http
host = 0.0.0.0
port = 5000

さて、今あるのは単に helloというアプリケーションだけです。
pastedeployでは、直接アプリケーションを参照するのではなく、アプリケーションを返す関数(ファクトリ)を指定するようになっています。

helloapp.py

def main(global_conf, **app_conf):
    return hello

今のところ特に設定を必要としてないので、さっきの hello をそのまま返すようにします。

$ paster serve hello.ini

で動きますね。

設定を使う
実際のところWebアプリケーションだと、データベースへの接続だとかそういった設定が必要です。
が、ここでSQLAlchemyの話を出すと説明しきれないので、messsageとか渡すことにしましょう。

設定をもとにアプリケーション作成するので、クラスにします。

class HelloApp(object):
    def __init__(self, message):
        self.message = message

    @wsgify
    def __call__(self, request):
        return self.message

def main(global_conf, message, **app_conf):
    return HelloApp(message)

で、 hello.ini は以下のように変更します

[app:main]
paste.app_factory = helloapp:main
message = Hello, world!

(´・ω・`)さて、ここからが本編です。
ええ、ここまでは、PasteDeploy自体知らないなんていう人が多いのではないかということで書きました。
なんせ、このアドベントカレンダーは8割がたDjangoネタですからね。おまいらフレームワーク1つしか知らないのか。

PasteDeployの設定を共有する
とりあえず設定値を2つにしてみます。

helloapp.py

class HelloApp(object):
    def __init__(self, message1, message2):
        self.message1 = message1
        self.message2 = message2

    @wsgify
    def __call__(self, request):
        return u"{0} {1}".format(self.message1, self.message2)

def main(global_conf, message1, message2, **app_conf):
    return HelloApp(message1, message2)

hello.ini

[app:main]
paste.app_factory = helloapp:main
message1 = Hello
message2 = world!

まあこんなもんです
が、たまにmessage1だけを変えたい時があるかもしれません。

そんなときには
セクションを追加します。

[app:hello]
use = main
message1 = Hi

このように use でセクションを指定して、変えたいところだけ設定します。
このappを実行するには、 paster serve に -n オプションで hello と指定します。

$ paster serve hello.ini -n hello

という、pastedeployで設定の共有や上書きができるよ。というお話でした。
これで、 production.iniやdevelopment.iniなどで、設定を共有しながら、デバッグフラグやDB接続など、必要な部分だけを変更して扱うことができますね。

19日目は @podhmo お願いします。