Hatena::ブログ(Diary)

bettermanの日記

2009-03-19

Werkzeugチュートリアル惰訳

| 18:35

データベースURLを格納するTinyURLクローンを作成する

Werkzeug0.2チュートリアルへようこそ。

このライブラリは、データベースレイヤのためのSQLAlchemyを利用するアプリケーション

テンプレートにjinjaを利用するアプリケーション、そして、もちろんWSGIレイヤのために

werkzeugを利用するアプリケーションで使用されることを想定しています。

私たちがチュートリアルアプリケーション用にこれらのライブラリを決めた理由は、

Djangoが過去にした設計決定のうちのいくつかに固執したいということです。

そのうちの1つは、アクションメソッドを備えたコントローラー・クラスの代わりに

ビューファンクションを使用することです。それはRailsPylonsにおいても共通の思想です。

他には、デザイナーにやさしいテンプレートを提供していることです。

Werkzeugのexample folderhttp://dev.pocoo.org/projects/werkzeug/browser/examplesには

あなたが好きなときに参照できる他のテンプレートエンジンを利用した一組のアプリケーション

含まれています。そしてそこには、そのアプリケーションソースコードもあります。

チュートリアルを実行するのには、まず、jinjaとSQLAlchemyを導入してください。

あなたがeasy_insatllを実行できる環境であるならば、以下のようにします。

sudo easy_install Jinja

sudo easy_insatll SQLAlchemy

私の環境では、以下のような実行結果となりました。

C:\>easy_install SQLAlchemy

Searching for SQLAlchemy

Best match: sqlalchemy 0.5.2

Processing sqlalchemy-0.5.2-py2.5.egg

Removing sqlalchemy 0.3.10 from easy-install.pth file

Adding sqlalchemy 0.5.2 to easy-install.pth file

Using c:\python25\lib\site-packages\sqlalchemy-0.5.2-py2.5.egg

Processing dependencies for SQLAlchemy

Finished processing dependencies for SQLAlchemy

C:\>easy_install Jinja

Searching for Jinja

Reading http://pypi.python.org/simple/Jinja/

Reading http://wsgiarea.pocoo.org/jinja/

Reading http://jinja.pocoo.org/

Best match: Jinja 1.2

Downloading http://pypi.python.org/packages/2.5/J/Jinja/Jinja-1.2-py2.5-win32.egg#md5=27b0804a126c2c0ebd4a9dacffb9dcbb

Processing Jinja-1.2-py2.5-win32.egg

creating c:\python25\lib\site-packages\Jinja-1.2-py2.5-win32.egg

Extracting Jinja-1.2-py2.5-win32.egg to c:\python25\lib\site-packages

Adding Jinja 1.2 to easy-install.pth file

Installed c:\python25\lib\site-packages\jinja-1.2-py2.5-win32.egg

Processing dependencies for Jinja

Finished processing dependencies for Jinja

もしあなたがWindows上でチュートリアルを試そうとしているなら、"sudo"ははずして実行してください。

(setuptoolsのインストールはわすれずに)

OS Xなら、portから、Linuxなら、package managerでpython-jinjaとpython-sqlalchemyとして実行してください。

Part0:フォルダ構成

チュートリアルを開始する前に、Werkzeugアプリケーションテンプレート、静的ファイルのためのフォルダを

作成する必要があります。チュートリアルアプリケーションは、チビ"shorty"と呼ばれます。

また、私たちが使用する最初のディレクトリ階層は以下のように見えます。

manage.py

shorty/

__init__.py

templates/

static/

__init__.pyとmanage.pyファイルは、当分の間空ファイルです。

最初に作成したshortyフォルダはpython packageです。二つ目に作成したものは管理ユーティリティを

保持するためのものです。

Part1:The WSGI Application - PEP333 Python Web Server Gateway Interface v1.0

Djangoや他のフレームワークとは違い、WerkzeugはダイレクトにWSGIレイヤにオペレーションします。

デベロッパのためにセントラルWSGIアプリケーションを実行するファンシーな魔法はありません。

あなたが、最初に書くのは、基底WSGIアプリケーションオブジェクト実装です。それは、関数にも

callable classにもなりえるでしょう。

callable classには、関数にはないアドバンテージがあります。

一つは、callable classにいくつかのコンフィグパラメーターを渡すことができます。

更に、インラインのWSGIミドルウェアを使用することもできます。

インラインWSGIミドルウェアは、基本的には私たちのアプリケーションオブジェクトの”内部に”適用できるミドルウェアです。

これは、アプリケーション (session middlewares, メディアファイルをサーブするような etc.)にとって

不可欠なミドルウェアに対する良い考えです。

以下に shorty/application.pyファイルというWSGIアプリケーションを実装するための最初のコードを示します。

#!/usr/bin/env python
# -*- coding: cp932 -*-
# via. Werkzeug Tutorial Part 1: The WSGI Application
# %PYTHONPATH%/werkzeug-0.4.1-py2.5.egg/docs/tutorial.html

from sqlalchemy import create_engine
from werkzeug import Request, ClosingIterator
from werkzeug.exceptions import HTTPException

from shorty.utils import session, metadata, local, local_manager, url_map
from shorty import views
import shorty.models

class Shorty (object):
    def __init__(self,db_uri):
        local.appliaction = self
        sefl.database_engine = create_engine(db_uri, convert_unicode=True)

    def init_database(self):
        metadata.create_all(self.database_engine)

    def __call__(self, environ, start_response):
        local.application = self
        request = Request(environ)
        local.url_adapter = adapter = url_map.bind_to_environ(environ)
        try:
            endpoint, values = adapter.match()
            handler = getattr(views,endpoint)
            response = handler(request,**values)
        except HTTPException, e:
            response = e
        return ClosingIterator(response(environ,start_response),
                               [session.remove,local_manager.cleanup])
    

このコードの大部分が始まりです。

ステップ by ステップで進めていきましょう。

最初に一組のインポート文があります。

From SQLAlchemyは新しいデータベースエンジンを生成するファクトリ関数インポートしています。

database engineは、データベース管理と、コネクションプールを保持しています。

次にWerkzeugネームスペースが提供しているいくつかのオブジェクトインポートがあります。

requestオブジェクト、リクエストの終了時に後始末を行ってくれる特別なイテレータ

そして全てのHTTP exceptionのためのベースクラスです。

私たちがutilsモジュールをまだ書いていないので、次の5つのインポートは動作しません。

しかしながら、オブジェクトのうちのいくつかを既にカバーすべきです。

sessionオブジェクトPHP風のセッションオブジェクトではなくSQLAlchemyデータベースセッション

オブジェクトです。基本的にデータベースセッションオブジェクトデータベース用に、

まだコミットされていないオブジェクトを追跡します。

Djangoとは異なり、インスタンス化されたSQLAlchemyモデルは、セッションによって

既に追跡されています!メタデータオブジェクトはさらに、テーブル情報を追跡するために

SQLAlchemyに使用されます。

デベロッパは、全てのデータベース用テーブルを作成するためにメタデータオブジェクト

容易に使用できます。また、SQLAlchemyは、外部キーおよび同様の材料を調べるために

それを使用します。

localオブジェクトは、ユーティリティモジュールに作成する基本的名スレッドローカルオブジェクトです。

このオブジェクト上の全ての属性は現在のリクエストに結び付けられます。

私たちは、暗黙にスレッドセーフな方法で、このオブジェクトを利用することができます。

local_managerオブジェクトは、リクエスト終わりで全てのlocalオブジェクトスレッドローカル)

プロパティ削除のための追跡方法を保持しています。

URLルーティング情報を保持するURLmapを最後にインポートしています。

比較することができるDjangoを知っているなら、urls.pyモジュールURLパターンを指定することができる。

PHPを使用しているなら、ビルトインの"mod_rewrite"と比較可能です。

デベロッパは、全てのモデルを保持しているmodelsモジュールとビュー関数を保持しているviewsモジュール

インポートします。

たとえインポートを使わないとしても、全てのテーブルがメタデータプロパティ上に登録されるように

そこにあります。

それでは、アプリケーションクラスを見てみましょう。

このクラスのコンストラクタは、データベースのタイプおよび、データベースログインクレデンシャル(信任状)

か、データベースロケーションをさすデータベースURIを受け取ります。

SQLiteの例は次のとおりです。'sqlite:////tmp/shorty.db'(スラッシュは4つです)

コンストラクタでは、データベースURIでdatabase engineを生成し、convert_unicodeパラメータ

SQLAlchemyにstringを全てunicodeオブジェクトに変換するよう伝えます。

他には、local object(スレッドローカル)へアプリケーションを拘束しています。

これは、実際必要ありません。ただし、python shellでアプリケーションを弄りたければ

有用です。

アプリケーションインスタンス化することで、カレントスレッドを拘束します。

そして全てのデータベース関数は、想定どおり動作するでしょう。

もしスレッド拘束を行わなければ、Werkzeugは、SQLAlchemyのためのセッションを作っている場合

データベースを見つけることができないと苦情を吐くでしょう。

コンストラクタの下に定義されているinit_database関数は、使用する全てのテーブルを作成するために

使用することができます。

その定義の後に、リクエストをディスパッチする関数が定義されています。

ここでは、Requestクラスのコンストラクタにenvironment(環境)を渡すことによって、

新しいrequestオブジェクトを生成しています。さらにもう一度、スレッドローカルにアプリケーション

拘束しています。拘束を行わなければ、アプリケーションはまもなく壊れます。

このとき、URL mapに現在のWSGI environmentオブジェクトで関連付けられている

新しいURL map adapterを生成します。これは、基本的に、入ってくるリクエスト情報の環境を

判断して、それが必要とする環境から情報を取得します。

これは例えば外部URLのためのサーバーの名前、スクリプトのロケーションなどです。

そのため、私たちはURL builderを使用して絶対パスを生成することができます。

さらに、utilsモジュール中でadapterをURL生成に使用することができるように、

私たちはアダプターをローカル(スレッドローカル)に拘束します。

その後、1つの、try/exceptで、HTTP exceptionをキャッチしています。

これは、adapterがマッチングしている間、あるいはビュー関数の中で生じるかもしれない

HTTP exceptionを補足しているのです。

アダプターが私たちの現在のリクエスト用の妥当なendpointを見つけない場合、

それは、私たちがレスポンス・オブジェクトのように使用することができるNotFound例外を投げるでしょう。

endpointは基本的に私たちがリクエストを扱いたい関数の名前です。

私たちは、endpointの名前を持った関数をちょうど得て、それにリクエストおよびURL値を渡します。

関数の最後では、response objectをWSGIアプリケーションとして呼び出しています。

そして、この関数戻り値(iterableとして)にclosing iterator classとともに、後始末用コールバック関数を渡します.

(callbacks:スレッドローカルの保持するデータのクリーンアップ、カレントSQLAlchemyセッションの削除)

次のステップでは、新たに2つの空ファイルshorty/views.pyとshorty/models.pyをつくります。

だから、事前にインポートしています。後で、この二つのファイルについてコードしていきます。

Part 2 : Utilities

今までで、基本的に、WSGIアプリケーション自体の実装は終了しています。しかし、

インポートしているクラスや関数が動作するように、utilityモジュールへさらにいくらかの

コードを加える必要があります。

当分の間、私たちは、アプリケーション動作に必要なオブジェクトを追加していくことになります。

以下に shorty/utils.pyファイルのコードを示します。

#!/usr/bin/env python
# -*- coding: cp932 -*-
# The Utilities

from sqlalchemy import MetaData
from sqlalchemy.orm import create_session, scoped_session
from werkzeug import Local, LocalManager
from werkzeug.routing import Map, Rule

local = Local()
local_manager = LocalManager([local])
# proxy objectが返る
application = local('application')

metadata = MetaData()
session = scoped_session(lambda: create_session(application.database_engine,
                                                transactional=True),local_manager.get_ident)

url_map = Map()
def expose (rule, **kw):
    def decorate(f):
        kw['endpoint'] = f.__name__
        url_map.add(Rule(rule,**kw))
        return f
    return decorate

def url_for(endpoint, _external=False, **values):
    return local.url_adapter.build(endpoint, values, force_external=_external)

最初に再び、ひと塊のコンポーネントインポートしています。

そして、既知のlocal object(スレッドローカル)とlocal managerオブジェクトを生成します。

ここで新しいことは、local objectをstringと共に呼び出すとproxy objectが返ることです。

この返ってきたプロキシは、常にlocal object上のその名前(local.__call__("application"))をもった属性を指します。

For example application now points to local.application all the time.

(local.applicationは常に、applicationをさします)

しかしながら、もし上のことを行わなかった場合、local.applicationには何もオブジェクトが拘束されていないので

RuntimeErrorを得ることになるでしょう。

次の3行は、SQLAlchemy0.4 またはそれ以降のバージョンで動作するWerkzeugアプリケーションで基本的に必要です。

私たちは、全てのテーブルのために新しいmetadataを生成します。そしてそのときに、scoped_session ファクトリ関数

を使って新しいscoped_sessionを生成します。

これは、基本的に、werkzeug localが行うよう、カレントコンテキストを決定し、かつ、

現在のアプリケーションデータベース・エンジンを使用するために同じアルゴリズムを使用するよう

SQLAlchemyに命令します。

もし、同一pythonインタプリタ上でアプリケーションオブジェクトの複数インスタンス化を提供したくないなら、

別の箇所でも、カレントlocal objectからアプリケーションオブジェクトを引くコードを無くせばシンプルになります。

この方法は、Djangoでも使われています。しかし、複数のこのようなアプリケーションオブジェクトの結合を不可能にします。

残りのモジュールは、私たちがviewsモジュールで使用するコードです。

基本的なアイディアとしては、Djangoのようなセントラルurls.pyや、PHPがやるようなURLリライトのための.htaccessではなく、

decoratorsを利用して、ビュー関数のためのURLディスパッチルールを決定する方法です。

これは一つの方法にすぎません。ルール定義のハンドル方法は無数にあります。

utils.pyのurl_for関数は、endpointによってURLを生成する単純な方法を提供します。

私たちは、viewsやmodelモジュールでこの関数を利用することになります。

Intermission : And Now For Something Completely Different

(休憩:全然関係ない話)

あなたは、日々の似通っている開発タスクに多くの時間がさかれています。

そのうちの一つが開発サーバーの立ち上げ(もし、あなたがphpユーザーなら:Werkzeugは、開発のためにApacheに依存しません。

完璧に素晴らしい推奨方法は、開発用pythonに同梱されているwsgiref serverを利用することです。)、次にpythonインタプリタ

開始させてdatabase modelsとの格闘、データベース初期化、などなど、

Werkzeugはそのようなmanagement scriptsを信じられないくらい簡単に作成します。

以下に完全にフィーチャーされたmanagement scripts実装を示します。

最初に作成したmanage.pyファイルの中にこの実装を入れます。

#!/usr/bin/env python
# -*- coding: cp932 -*-
# manage.py

from werkzeug import script

def make_app ():
    from shorty.application import Shorty
    return Shorty('sqlite:////tmp/shorty.db')

def make_shell ():
    from shorty import models,utils
    application = make_app()
    return locals()

action_runserver = script.make_runserver(make_app,use_reloader=True)
action_shell = script.make_shell(make_shell)
action_initdb = lambda : make_app().init_database()

script.run()

werkzeug.script は、script documentation(file:///C:/Python25/Lib/site-packages/werkzeug-0.4.1-py2.5.egg/docs/script.html)

で詳細に説明してあるのでここでは割愛します。

もし、上述したコードと、あなたのコードの比較と行番号による例外チェックを行いたいなら。

何が重要かというと、python manage.py shellを実行することで、tracebackなしで、インタラクティブpythonインタプリタ

取得できるということです。

すぐにでも、スクリプトを走らせて、database modelsモジュールを書き始めることができるのです!ひゃっほー!

Part 3 : Database Models

既に私たちはmodelsモジュールを作ることができます。

なぜなら、applicationは、tableと一つのモデルだけを持つシンプルでprettyなものだからです。

#!/usr/bin/env python
# -*- coding:cp932 -*-
# models.py

from datetime import datetime
from sqlalchemy import Table , Column, String, Boolean, DateTime
from shorty.utils import session,metadata,url_for,get_random_uid

url_table = Table('urls',metadata,
                  Column('uid',String(140),primary_key=True),
                  Column('target',String(500)),
                  Column('added',DateTime),
                  Column('public',Boolean)
                  )
class URL(object):
    def __init__(self, target, public=True, uid=None, added=None):
        self.target = target
        self.public = public
        self.added = added or datetime.utcnow()
        if not uid:
            while True:
                uid = get_random_uid()
                if not URL.query.get(uid):
                    break
        self.uid = uid

    @property
    def short_url(self):
        return url_for('link',uid=self.uid,_external=True)

    def __repr__(self):
        return '<URL %r>' % self.uid

session.mapper(URL, url_table)    

このモジュールは、かなり真っ直ぐです。テーブル作成に必要なSQLAlchemyモジュールを全てインポートします。

そして、このテーブルのために、クラスを加えて、マッピングします。

SQLAlchemyに関する詳細な説明に関しては、excellent tutorial(http://www.sqlalchemy.org/docs/04/ormtutorial.html)

を見ましょう。

コンストラクタでは、自由に使用できるIDが見つかるまで、ユニークなIDを生成します。

sqlalchemy.utils.get_random_uid関数が見当たらないことにならないように、sqlalchemy.utilsモジュール

追加しておきましょう。

今回は、606行目あたりに以下のget_random_uid関数を追加しておきました。

# For Werkzeug Tutorial Application util function
URL_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
def get_random_uid ():
    from random import sample, randrange
    return ''.join(sample(URL_CHARS, randrange(3,9)))

今日はここまで。

trac-jaいれた

| 16:53

trac入れたときのメモ。

まぁ、いわずと知れたtracです。

プロジェクト管理・バグトラッキングツール

修正BSDライセンス

[構成]

apache2.2 + mod_python + trac-ja

[特徴]

python

バグデータベース

wiki間のハイパーリンク情報を提供

svn,git,hg,bzrといったバージョン管理システムのwebインタフェースを提供

[必須stuff]

python(自分の環境はpython2.4)

sqlite3 ※ python2.5 laterなら同梱されてるから必要ないです。

easy_install

$ wget http://www.i-act.co.jp/project/products/downloads/Trac-0.11.2.1.ja1.zip

$ unzip Trac-0.11.2.1.ja1.zip

$ cd Trac-0.11.2.1.ja1

$ sudo python setup.py install

running install

running bdist_egg

running egg_info

creating Trac.egg-info

writing requirements to Trac.egg-info/requires.txt

writing Trac.egg-info/PKG-INFO

writing top-level names to Trac.egg-info/top_level.txt

writing dependency_links to Trac.egg-info/dependency_links.txt

writing entry points to Trac.egg-info/entry_points.txt

writing manifest file 'Trac.egg-info/SOURCES.txt'

reading manifest file 'Trac.egg-info/SOURCES.txt'

writing manifest file 'Trac.egg-info/SOURCES.txt'

installing library code to build/bdist.linux-i686/egg

running install_lib

running build_py

...

Installed /usr/lib/python2.4/site-packages/Genshi-0.5.1-py2.4-linux-i686.egg

Searching for setuptools==0.6c9

Best match: setuptools 0.6c9

Processing setuptools-0.6c9-py2.4.egg

setuptools 0.6c9 is already the active version in easy-install.pth

Installing easy_install script to /usr/bin

Installing easy_install-2.4 script to /usr/bin

Using /usr/lib/python2.4/site-packages/setuptools-0.6c9-py2.4.egg

Finished processing dependencies for Trac==0.11.2.1.ja1

[tracプロジェクト作成]

trac-adminを利用してTrac environmentを作成。インストールが正常終了していれば利用できる。

$ sudo mkdir -p /usr/local/trac/projects/dev/

$ # Trac environment初期化

$ trac-admin /usr/local/trac/projects/dev initenv

※tracEnvを作成するのに必要な情報が聞かれます。

・プロジェクト名

データベースコネクションストリング ※デフォルトsqlite

リポジトリタイプ ※デフォルト:svn

リポジトリパス ※/usr/local/trac/projects/dev

$ # Trac environmentの所有者をapacheユーザーに変更

$ sudo chown -R apache:apache /usr/local/trac/projects/

$ # 動作確認

$ sudo tracd --port 8001 /usr/local/trac/projects/dev #port 8001でアクセス。メインページが見れたらおk

[Trac設定]

匿名ユーザーからロールを剥奪

$ sudo trac-admin /usr/local/trac/projects/dev permission remove anonymous TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY

・チケットプロパティの日本語化

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type add タスク-task

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type add 機能追加/変更-enhancement

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type add 不備/不具合-defect

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type remove defect

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type remove task

$ sudo trac-admin /usr/local/trac/projects/dev/ ticket_type remove enhancement

[Trac plugins]

プラグイン公開サイト:http://www.trac-hacks.org/wiki/

・TicketImportPlugin : http://trac-hacks.org/wiki/TicketImportPlugin

Excel , CSV形式のファイルを読み込んでチケットを登録するためのプラグイン

$ sudo easy_install http://trac-hacks.org/svn/ticketimportplugin/0.11 # CSV読み込みできる

$ sudo easy_install xlrd # Excelの読込ができる。

$ # trac.iniの編集

$ sudo vi /usr/local/trac/projects/dev/conf/trac.ini

[components]

talm_importer.importer.* = enabled

IMPORT_EXECUTE権限を付与(htpasswdでBasic認証を行う予定なので、authenticatedユーザーに対して付与)

$ sudo trac-admin /usr/local/trac/projects/dev/ permission add authenticated IMPORT_EXECUTE

・XmlRpcPlugin : http://www.trac-hacks.org/wiki/XmlRpcPlugin

eclipse mylyn pluginと連携するときに必要なのでインストール

$ sudo easy_install http://trac-hacks.org/svn/xmlrpcplugin/trunk/

TRAC_ADMIN権限を持っているアカウントで、tracログインして、管理からプラグインを選択。

XmlRcpPluginが表示されるので、全て選択し適用。

XML_RPC権限を付与

$ sudo trac-admin /usr/local/trac/projects/dev/ permission add authenticated XML_RPC

[apache confファイル]

httpd.confでincludeするconfファイルを作成。以下定義内容。

# trac Location directive

<Location /trac>

SetHandler mod_python

PythonHandler trac.web.modpython_frontend

PythonOption TracEnvParentDir /usr/local/trac/projects/

#PythonOption TracUriRoot /xxx/xxx

PythonDebug on

</Location>

# trac login LocationMatch directive

<LocationMatch "/trac/.*/login">

AuthType Basic

AuthName "trac"

AuthUserFile "/usr/local/trac/projects/.htpasswd"

Require valid-user

</LocationMatch>

おわり。

MoinMoin 1.8.1 入れたときのメモ(CentOS5.2 final)

| 15:41

MoinMoin構成

apache2.2 + mod_wsgi + MoinMoin1.8.1

[特徴]

python wikiエンジン

DB依存なし。

ページリビジョン管理(変更履歴は全て保存される->だから重い)

UTF-8対応

WYSIWYGエディタ

拡張マクロ、テーマとか(http://moinmo.in/MoinMoinExtensions)

[事前準備]

以下のモジュールを導入しておく。全てyumで導入

apache2-threaded-dev #apxs2がmod_wsgiのビルドに必要っぽいので。

httpd-devel #一応、apxsもいれとく

mod_wsgi2.1-2.el5.i386 # mod_wsgi

[moinmoin導入]

$ sudo wget http://static.moinmo.in/files/moin-1.8.1.tar.gz
$ #展開する
$ gzip -dc moin-1.8.1.tar.gz | tar xvf -
$ cd moin-1.8.1
$ #setup.pyを叩いてインストール & record install log
$ #--prefix指定なしなので、標準インストール /usr/share/moinにインストールされます。
$ #MoinMoinのpythonモジュールは、PYTHONPATHに配置されます。
$ #私の環境では、/usr/lib/python2.4/lib/site-packages/MoinMoin
$ sudo python setup.py install --record=install.log
$ #今回作成するMoinMoinWiki用のディレクトリを作成
$ sudo mkdir -p /usr/local/moin/wiki/
$ #MoinMoinインストールディレクトリから必要なファイル等をディレクトリ毎コピります。
$ export WIKI_HOME=/usr/local/moin/wiki/
$ export MOIN_CONFIG=/usr/share/moin/config/
$ export MOIN_DATA=/usr/share/moin/data/
$ export MOIN_HTDOCS=/usr/share/moin/htdocs/
$ export MOIN_UNDERLAY=/usr/share/moin/underlay/
$ export MOIN_SERVER=/usr/share/moin/server/
$ sudo cp -R $MOIN_CONFIG $WIKI_HOME
$ sudo cp -R $MOIN_DATA $WIKI_HOME
$ sudo cp -R $MOIN_HTDOCS $WIKI_HOME
$ sudo cp -R $MOIN_UNDERLAY $WIKI_HOME
$ sudo mkdir -p $WIKI_HOME/apache # <- mod_wsgiが参照するディレクトリを掘る
$ sudo cp -v $MOIN_SERVER/moin.wsgi $WIKI_HOME/apache/
$ # mod_wsgi用の設定ファイル編集
$ sudo vi $WIKI_HOME/apache/moin.wsgi
以下オリジナルとのdiff
< sys.path.insert(0, '/usr/lib/python2.4/site-packages')
---
> sys.path.insert(0, '/usr/local/moin/wiki/config/')
$ # Wikiコンフィグレーションファイル wikiconfig.pyを編集
$ cd $WIKI_HOME/config/
$ sudo vi wikiconfig.py
以下オリジナルとのdiff
< # -*- coding: utf-8 -*-
---
> # -*- coding: iso-8859-1 -*-
9d8
< 
37c36
<     sitename = u'Develop Team Wiki'
---
>     sitename = u'Untitled Wiki'
50c49
<     page_front_page = u"FrontPage"
---
>     #page_front_page = u"FrontPage"
70c69
<     data_dir = '/usr/local/moin/wiki/data/'
---
>     data_dir = '/usr/local/apache/html/moin/data/'
78c77
<     data_underlay_dir = '/usr/local/moin/wiki/underlay/'
---
>     data_underlay_dir = '/usr/local/apache/html/moin/underlay/'
87c86
<     url_prefix_static = '/moin_static181'
---
>     #url_prefix_static = '/moin_static181'
94c93
<     superuser = [u"specialuser", ]
---
>     #superuser = [u"YourName", ]
99c98
<     acl_rights_before = u"specialuser:read,write,delete,revert,admin"
---
>     #acl_rights_before = u"YourName:read,write,delete,revert,admin"
104c103
<     password_checker = None # None means "don't do any password strength checks"
---
>     #password_checker = None # None means "don't do any password strength checks"
143d141
<     #theme_force = True
145,147c143
<     #theme_force = True
<     theme_default = 'modern' 
<     #theme_default = 'sinorca4moin'
<     #theme_default = 'explorer'
<     #theme_default = 'simplemente'
---
> 
155c151
<     language_default = 'ja'
---
>     language_default = 'en'

[今まで行った作業]

・MoinMoinの標準インストール

PREFIX/lib/pythonX.Y/site-pacakges/MoinMoinにモジュール群が配置されます。

/usr/share/moin/直下に構成ファイルなどのテンプレートが配置されます。

ディレクトリ構成は以下のとおりです。

/usr/share/moin/

/data/ (wiki pages, users, etc) - 当ディレクトリはMoinMoinのみがアクセスすべきディレクトリ

/underlay/ (wiki pages) - 当ディレクトリはMoinMoinのみがアクセスすべきディレクトリ

/htdocs/ (htmlサポートファイル[テーマとか,imageとか]) - apacheが参照するディレクトリ。シムリンクでもお好きに。

/server/ (MoinMoinスタートアップファイル配置ディレクトリ)

/config/ (MoinMoinコンフィグレーションファイル配置ディレクトリ)

[Apache2.2 + mod_wsgi]

mod_wsgiはyumインストールしているので、apacheモジュールディレクトリに配置されています。

moinmoin用のconfファイルを作成して、httpd.confでincludeします。

以下confファイル定義。

# wsgi_module load
LoadModule wsgi_module modules/mod_wsgi.so
# moinmoinで利用する静的コンテンツ置き場へのエイリアスディレクティブ定義
Alias /moin_static181 /usr/local/moin/wiki/htdocs/
# /moin_static181のDirectoryディレクティブ定義
<Directory /moin_static181>
  Order deny,allow
  allow from all
</Directory>
# WSGIScripAliasディレクティブ
WSGIScriptAlias /wiki /usr/local/moin/wiki/apache/moin.wsgi
# moin.wsgiをmod_wsgiがハンドルできるようにDirectoryディレクティブ定義
<Directory /usr/local/moin/wiki/apache>
  Order deny,allow
  Allo from all
  SetHandler wsgi-script
  Options ExecCGI
</Directory>

apacheが見るディレクトリの権限をリカーシブでapacheユーザーに変更。

gracefulしてhttp://my.domain/wiki/アクセスしてFrontPageが表示されれば成功。

あとは、各利用ユーザの権限管理とかをよきにはからえばおk