tracdをserviceだかdaemonだかでアレする

trac動くようになったのはいいんだけど、サービスとして起動したい。
あたしがサーバから出るとtracも死んでるとか意味不明すぎる。

http://trac.edgewall.org/ticket/4352
ここ読んだ。

なんか起動しないぞって時は、

/var/run/tracd
/var/lock/subsys/tracd

このへん?になんかロックファイルみたいなもんが出来てるかもねとのこと。
はー。なるほどー。

Tracのセットアップをする

あたくしの周辺ではredmineの利用事例が圧倒的多数を占めている感がありますが、宗教的な理由により自分のサーバにまで積極的に赤い石ころを入れる気にはなりません。

さしあたり経緯や理由はどうでもいいので、備忘としてtracを入れてちゃんと動くアレを残しておきます。
#あくまで自分用です
#CentOSにいれたもんでTrac-Lightningは選択できない
#Kanonなるものを見つけたけど、まあなんかダメだった

参考にしたページ

TracInstall – Sandbox Trac-0.11.7.ja1
TRAC-ADMINのオプションに関するリファレンス・ドキュメント
プロジェクトの始まりはTracから – @masuidrive blog

環境

  • CentOS(さくらのVPS)
  • Nginx
  • Python2.7

環境あんま関係ない手順ですが一応。

アーカイブ入手

pip install trac

おわり。Trac-1.0.1が入りました。
久々にGenshiとかも入っちゃって懐かしい限り。もうテンプレート読んでも分かんない気がする。
プラグインはなんとなく、主要なのが入ってる気配。

trac-admin /path/to/myproject initenv

でプロジェクト作って、

tracd -p 8000 . –basic-auth=fooproject,/path/to/passwddir/.htpasswd,/path/to/fooproject \
/path/to/fooproject

パラメータのあれはよくわかってない。

nginx.conf

nginxは設定が楽でよい。

server {
    listen       80;
    server_name fooproject.example.com;
    location / {
        proxy_pass  http://localhost:8000;
        root   /path/to/fooproject/htdocs;
        index  index.html index.htm;
        auth_basic "member only";
        auth_basic_user_file /path/to/passwddir/.htpasswd;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    location ~ /\.ht {
        deny  all;
    }
}

trac.ini

ほとんど理解はしてないが、

src = site/img/fuaulogo.png

これが、

http://trac.example.com/fooproject/chrome/site/img/fuaulogo.png

といった具合になるということはわかった。
siteとcommonとがある云々。
この状態で実ファイルは、htdocs/img下に置いてある。
この仕掛けを理解するだけでけっこうかかった(‘・ω・`)

Todo

Gitとの連携どうやんだろうなあ。

LeapPython ImportError

>>> import LeapPython
Traceback (most recent call last):
File ““, line 1, in
ImportError: DLL load failed: %1 は有効な Win32 アプリケーションではありません。

もういい。スカイリムでもやろう。
いやその前にWebSocketいじるとか、まあ、あれだ、LeapMotionはしばらく埃かぶっててもらおう。
はー。

Leap Motion with Python

もーなんか、なんつうの、ほっといてもモチベーションがぐわーと上がるとかもないのんで、仕方ないので重い腰を上げることにするのよ。
なんで買った途端にモチベーション下がってんだ。

なんとなくPYTHONPATHを通してみる

結論から言うけどダメ。

>>> import Leap
Traceback (most recent call last):
File ““, line 1, in
File “C:\Program Files (x86)\Leap Motion\LeapSDK\lib\Leap.py”, line 31, in
LeapPython = swig_import_helper()
File “C:\Program Files (x86)\Leap Motion\LeapSDK\lib\Leap.py”, line 23, in swi
g_import_helper
import LeapPython
ImportError: DLL load failed: %1 は有効な Win32 アプリケーションではありません。

ああ。やる気なくなる。
いちいち説明するのもめんどくさいので、いきなりゴールにいきますね。

正解:全部同じディレクトリに放り込む

乱暴極まりない。なんだこれ。
あたしんちの場合ですと、site-packages下にleapというディレクトリを掘りまして、

C:/Python27/Lib/site-packages/leap
__init__.py #空ファイル作る
Leap.dll
Leap.lib
Leap.py
LeapCSharp.dll
Leapd.dll
Leapd.lib
LeapJava.dll
LeapPython.pyd
msvcp100.dll
msvcp100d.dll
msvcr100.dll
msvcr100d.dll

Leap.pyと、その下にあったx86もしくはx64の下をぜんぶおなじとこに散らかすことでセットアップ終わります。

>>> from leap import Leap
>>> Leap

ふー。
やっと取り掛かれるって寸法ですぜ。

さんざっぱらエラー吐かれている時に、

fp, pathname, description = imp.find_module(‘LeapPython’, [dirname(__file__)])

なんでここ探してんのかなーって気づく視点が必要でした。
まだまだPythonに慣れてない感じよ。

余談

PyPi探してみると、どーもleapって名前の技術かなんかがあるみたい。
ディレクトリ名はleapmotionとかにした方がいいのかもね。
あたしはそのままやるけどね。

英数字混在の文字列から英文字を剥がす

剥がすというか数字だけ抜き出した文字列にする。
こういうチョイチョイしたものをどうするかで思考時間発生することが多いので、さしあたりメモ書き。

''.join([x for x in "1F2GG345" if x in "1234567890"])
→'12345'

スマートではないけれども。

仕事のちょっとした作業をリモートでやるのにgoogle drive使いました。
いやーこれべんりだねえ。
グループで使えるDropBoxみたいなかんじ。変な挙動する気配あるけど、おおむねいいかんじ。オッケー☆

initializedb.py

initialize_Xxx_db.exeとかであれしますねDBの初期化とか。

 ../Scripts/initialize_Xxx_db development.ini

みたいな。
これどこでセットアップするテーブルの一覧見てんのかなーというと、
Xxx/xxx/scripts/initializedb.py
でした。

うちの環境は

models/
  models.py
  users.py

こうです。scaffoldのmodels.pyがそのまま生存しているのでなんか紛らわしい。よくない。よくないお。

で、件のinitializedb.pyのなかでモデル取り出してるところがあったのでー

from ..models.models import (
    DBSession,
    Base,
    )
from ..models import (
    models, users
    )

こんなふう。

#備考:
#あたしんちはmodelsディレクトリ切ってその中にモデルのファイルを入れています。
#なのでmodels/__init__pyにこんなふう。

# -*- coding:utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

ルート直下にviews.pyとか散らかしたくない

#pcreate -s alchemy Hoge で作ったプロジェクトを例にしています
App/app/views/views.py
とかしたい。

__init__.py

config.scan('.views')

このようにせいと、マニュアルに書いてある
この「.views」ってなんじゃ。ドットから始まるディレクトリ掘るというのはいささか悪趣味に感じるんだけど。

views掘ってみる。__init__.py置く。views.pyをそこに格納。
これだけだと

ImportError: No module named models

なんてerror吐かれて、あたしゃビューの面倒見てんのになんでモデルがしゃしゃり出てくるんだと奇妙な感じ。
なんだろうなあとviews.pyを眺めて、はたと膝を打つ。

from .models import (
    DBSession,
    MyModel,
    )

これだ。

from ..models import (
    DBSession,
    MyModel,
    )

こうする。微妙すぎてあれだけど、「.models」→「..models」になってる。
いつのバージョンだかからこういう指定の仕方できるようになったんですみたいな話を聞いていたのが救いになった。
で、件の「.views」も同じことだったわけかーと納得した次第です。
カレントディレクトリの下のviewsをscanするから「.views」なのねー。

あー。modelのスクリプトもmodels/models.pyとかにしたい場合は、views.pyでのモデルの場所指定も変わるね。

MakoじゃなくてJinja2使いたい

Pyramidのわだいです。

“.mak” または “.mako” で終わるテンプレートファイル名は Mako レンダラー に送られます。
“.html”のような他の拡張子が使いたければ、 main 関数に これを入れてください:
config.add_renderer(“.html”, “pyramid.mako_templating.renderer_factory”)
引用元

で、こういうののjinja2はどうしたらいいのか探してましたのよ。
pyramid.mako_templating.renderer_factory
これはなーに?どういう決まりでこれになってんの。分からない。
あたしはMakoを使うつもりがない。いいテンプレートエンジンなのは知ってる。少し。あたしの好みはJinja2でありGenshiなので、Jinja2が動いてくれないと嫌なのです。
#Genshiはちょっと気難しい子なので最近は避けてます(-_-;

Jinja2のテンプレートを食わせるまではうまく行った。
がしかし、拡張子「.jinja2」が非常に気に入らない。長いしダサいしそもそも数字がついてるのが非常に駄目だ。
あたしゃテンプレートの拡張子.htmlじゃなきゃ嫌なんだよ。
でもなんだか、中のほうで拡張子ごとにゴニョゴニョしている箇所があるらしく、テンプレートファイルとしてhoge.jinja2を単純にhoge.htmlとしてもうまくいかない。

あちこちさまよった結果、

config.add_renderer(".html", "pyramid_jinja2.renderer_factory")

__init__.pyでこうしてやるとうまくいった。.htmlでも食べるようになる。やった。
そもそもこの文字列はどこで見つけたのかというと、site-packagesのpyramid_jinja2見に行って、configure.zcmlつう怪しいファイルの中に書いてあるのを発見したという次第。
見つけ方合ってるのかわかりませんが解決したからいいんだ。

まとめ

当然のこととしてjinja2とpyramid_jinja2はいれとく

development.ini:

[app:main]に追記
jinja2.directories = %(here)s/{アプリ}/templates

pyramid.includesに追記
pyramid_jinja2

アプリ直下の__init__.py:

config = Configurator(settings=settings)
config.include('pyramid_jinja2')
config.add_renderer(".html", "pyramid_jinja2.renderer_factory")

まだ「リソースとビュー」の考えかたは染みこんできてない。
モデルよりフレームワークの仕掛けより、あたしはまず好みのテンプレートエンジンが動かないと気分的に落ち着かず、ただでさえ少ない集中力が減退する構造になっているんです。
というところがすっきりして、ひじょーに、こう、いいですね。
すっきりしました少し。

Pyramidにはコントローラがない

絶対どこかで議論されたはず。混乱する人があたしだけ、なんてわけない。
そう、そんなわけはなかった。

「私は MVC ウェブフレームワークのユーザですが、混乱しています。 Pyramid はコントローラーをビューと呼んでいます! そして コントローラーがありません。」
引用元

これ。そしれこの文章自体が、Pyramid公式に載っているのをまんま引用したもの。
MVCがWebの仕事を正確に表現できてると思わないので、「リソースとビュー」というもので表現することにしましたと書いてある。
ええええ。

  • リソースツリーはサイト構造を表わします。
  • ビューは リソースを示します。
  • テンプレートは実際には単に任意のビューの実装詳細です
  • ビューは、レスポンスを返すためにテンプレートを必要としません。
  • 「コントローラー」は、ありません
  • 「モデル」は、 リソースツリー、またはフレームワークと完全に分離した「ドメインモデル」 (SQLAlchemy モデルのような) によって表わされます。

なんだそれは。
なんなんだそれは。
道理で、あたしの理解がまっったく進まないわけだ。
Pyramid使い始めてみたものの全然分からなくて、ああもうあたしのお脳の理解力の限界はここなのかお粗末な話だなこんちくしょう、って思ってたわけです。
10年近くくらいはMVCMVCって言われてきたんでないですか、Webの世界って。それがここにきて考え方を変えましょうときたわけで、そりゃ混乱するよねと。
リソースとビュー。
リソースとビューですよ奥さん。

config.add_route('home', '/')

こんなんやってる箇所が地図作ってるわけだな。
ツリー構造のurlマップみたいなのがリソースの地図になっていて、リソースそのものがビュー。
テンプレートは実装詳細です。そうですか。必ずしもテンプレートが必要なわけではないとあるあたりが理解の鍵なのかしらん。

モデルはフレームワークの格にあるんじゃなくて外側なんだと。そうなの、データって外側に位置するの。ちょっとイメージが出来てないですが、一旦そういうもんだと覚えることにする。
MVCのMに当たるのがーとか変換して考えちゃうから苦しむんであって、これはパラダイムが変わって別物が出てきたんですよというくらいで捉えるほうがよさそうです。

#あたしのお脳はまだついてきてません

Pyramidのプロジェクトをさくっと作る

自分用メモ
各位ご存知のことかと存じますが、あたしはお脳のメモリ容量、アクセス速度共に石器時代あたりの人でありますので、pyramidのセットアップ一つをするりとやっつけるのにすらあちこちで転んでおりました。
わかってみると道理の通った手順なのですが、わかるまでが遠い。「何のためにこれやってんの」「どこに書いてあるの」「これやるとどうなるの」「いつおわるの(´・ω・`)」と不安になり腕が震え膝が体を支えられなくなり冷や汗が額を流れ落ちエトセトラ。
で、もうめんどくさいからこういうのを書いとけばいいんだよ。
#batファイルとして書いてるのでバックスラッシュです一部

:: pyramidstart.bat
@echo off
IF "%1" == "" (
    echo "pyramidstart env(virtualenv) project(pyramid)"
) else (
    virtualenv %1
    cd %1
    Scripts\activate
    pcreate -t alchemy %2
    cd %2
    pip install jinja2
    pip install pyramid_jinja2
    pip install -e .
    setup.py test -q
    \Scripts\initialize_%2_db development.ini
    echo "plz type: pserve development.ini --reload"
)

jinja2は入れただけなのでじつは

pyramid.includes =
    pyramid_jinja2

こういうのを(たぶん)書き加えてあげる必要があるんですが、さしあたりざくっと「Welcome to Hoge」画面を出すには足ります。
virtualenvの環境名fooenv
pyramidのプロジェクト名Foo
のばあい

pyramidstart fooenv Foo

とやると。