ひよっこ。

I want to…

Posts Tagged ‘trac’

TracのReadonlyの背景を変更する

Posted by hikaruworld : 2010 2月 17

TracにはWikiページをReadonlyにすることが出来ます。
但しReadOnlyにしたからといって、Wikiページの見た目が変更されるわけではありません。
(ADMIN権限がないユーザで編集ボタンが表示されなくなりますが)

基本的には上記の動作で困りません。
ところが、自分が編集しない意味でreadonlyにした場合でも、気が付かずに編集してしまうことがあったので、
readonly時に背景を変更するように対応してみました(プレビュー時のイメージです)

※「自分が編集しない意味でreadonlyにした場合」の例としては、例えば顧客の承認を得たような文書です。

以下、本題です。

Trac0.11では、tracプロジェクト/templatesにsite.htmlを置くことでGenshiを利用したヘッダー/フッダー/CSSのカスタマイズを行うことが出来ます。
私の環境だと複数環境Tracのtemplatesを共有化させるために、以下のような設定をしていますので/hoge/templatesDir/のsite.htmlの編集をします

[inherit]
templates_dir = /hoge/templatesDir/

site.htmlは以下のようにしてreadyonly.pngを読み込ませるようにしました。

<!-- ReadOnly customize -->
<py:if test="req.environ['PATH_INFO'][0:5] == '/wiki'">
	<py:if test="page.readonly">
		<style type="text/css">
		<!--
		body {
			background:url(/htdocs/readonly.png);
		}
		-->
		</style>
	</py:if>
</py:if>

あわせて、trac.iniで設定している”htdocs_location”にreadonly.pngを設定すると、
readyonlyページが以下のようになります。

以上です。

広告

Posted in program | タグ: | Leave a Comment »

Tracの任意のWikiページをPDF出力するスクリプトを作ったよ(暫定版)

Posted by hikaruworld : 2010 1月 7

TracのPDF出力する方法は、以前の記事でも述べたようにいくつかあります。
が、その中で唯一日本語に対応しているTracWikiExportプラグインは、
残念な事にテーブル内に日本語構成が含まれていた場合にテーブル構造が崩れたり、

{{{#!html}}}

を正しく解釈できないという微妙な問題を含んでいます。

それで困っていたので、簡単にJavaのPDF出力ライブラリのiText5を利用して作ってみました。
サラッと作っただけでまだバグバグですが、コアとなるJavaの部分だけ晒しておきます。
launchpad.netにあげているので、ここからダウンロードできます。
目標としてはAdobeAirを利用したプレビュー機能&ダウンロード機能をつけたいですね。

ちなみに、プラグインとして作らずにAPIを利用して別アプリとして作ったのは、
PDF出力する状況を考えるとTrac上にプラグインとして存在する必要もないかなと思ったので。
むしろ、管理者レベルがある特定のタイミング(納期や外部との打ち合わせ)で利用するだけかなと。

使い方

実行可能jar形式なのでjava -jar で実行してください。
その際引数に、TracのXML-RPCプラグインのURL(認証には未対応),出力先,対象Wikiページ,の指定が必要になります。
以下サンプルです。

java -jar TracPDFConvertor.jar http://localhost:8080/trac/sample/xmlrpc /Output TracGuide,WikiFormatting,Hoge/HelloWorld,Piyo/*

いくつか補足します。
第一引数ではxmlrpcで接続先を指定するのでxmlrpcプラグインが必須です。
ただし、現状では認証に対応していませんので注意してください。

第三引数は、出力したいWikiページをカンマ区切りで指定します。
その際、サブディレクトリ構造を持つWikiページはそのまま指定してください(Hoge/HelloWorld)。
任意のサブディレクトリ構造以下を指定したい場合は*指定が使えます。上記のサンプル(Piyo/*)ではPiyo以下のすべてのWikiページを出力します。

出力結果は以下の通りです。

/Output/TracGuide.pdf
/Output/WikiFormatting.pdf
/Output/Hoge/HelloWorld.pdf
/Output/Piyo/1.pdf
/Output/Piyo/2.pdf

Wikiページ名+.pdfファイル名で出力が行われます。
また、サブディレクトリ指定の場合はサブディレクトリ単位でディレクトリが生成されます。

WikiFormattingの出力結果のファイルを添付しておきます。

TODO

  • AdobeAirのアプリケーションでラップする(JWSとかじゃないのは単なる趣味)
  • Wordへの出力
  • 出力形式の整形
  • Imageなどでリンク先のファイルが存在しない場合にIOExceptionで落ちる
  • スタイルシート及びフォントの設定などをプロパティから読み込めるようにする
  • 接続先Tracのスタイルシート設定の解析

ソースコードはここにあります。

xmlrpcclientで通信して、対象ページのHTMLを取得した後、iTextで書き出しているだけです。
また、外部ライブラリとして、iText5及びApacheXmlRpc、日本語フォントとしてIPAモナーフォントを利用しています。感謝。

以上です。

Posted in program | タグ: , , , , | Leave a Comment »

tracのstandalone.pyでログイン機構を利用する

Posted by hikaruworld : 2009 12月 27

tracには開発用にスタンドアローンで起動可能なスクリプトstandalone.py
trac/web以下に存在しており、大変便利です。

起動は、以前も書いたように

-p 8080 /PATH_TO_TRAC_PROJECT/sample

として、-pで起動ポート番号と対象のtracプロジェクトを指定するのみというお手軽さ。

これはこれで非常に便利なのですが、
権限テストなどを行うような場合はtracのログイン機構を利用したくなります。
要するに認証情報ですね。

tracdで起動した場合、認証機構は無効になっておりLoginを押下しても以下のようなエラーが出ます。

Trac Error
Authentication information not available. Please refer to the installation documentation.
TracGuide — The Trac User and Administration Guide

そのため認証を行いたい場合は、
認証用のhtdigestを作成しておいて、起動時に以下の様に引数を与える必要があります。

-a sample,/trac.htdigest,tracd

以下は認証用のhtdigestファイルです。最後の文字列はmd5でadminというパスワードを暗号化したものです。

admin:tracd:d1d5105feef38ad528a53373c8e5d556

ちなみに、standalone.pyには他にもこんな引数が準備されています(standalone.py -hで確認)。

Usage: standalone.py [options] [projenv] …

Options:
–version show program’s version number and exit
-h, –help show this help message and exit
-a DIGESTAUTH, –auth=DIGESTAUTH [projectdir],[htdigest_file],[realm]
–basic-auth=BASICAUTH [projectdir],[htpasswd_file],[realm]
-p PORT, –port=PORT the port number to bind to
-b HOSTNAME, –hostname=HOSTNAME the host name or IP address to bind to
–protocol=PROTOCOL http|scgi|ajp
-q, –unquote unquote PATH_INFO (may be needed when using ajp)
–http10 use HTTP/1.0 protocol version (default)
–http11 use HTTP/1.1 protocol version instead of HTTP/1.0
-e PARENTDIR, –env-parent-dir=PARENTDIR parent directory of the project environments
–base-path=BASE_PATH the initial portion of the request URL’s “path”
-r, –auto-reload restart automatically when sources are modified
-s, –single-env only serve a single project without the project list
-d, –daemonize run in the background as a daemon
–pidfile=PIDFILE When daemonizing, file to which to write pid
–umask=MASK When daemonizing, file mode creation mask to use, in octal notation (default 022)

以上です。

Posted in program | タグ: , | Leave a Comment »

Wordで差分管理するのは現実的?

Posted by hikaruworld : 2009 12月 19

@coelacanthが書いた記事が興味深かったのでトラックバック。

差分が取れないというのはもちろんですが、仕様書やチャートなどをバージョン管理することの効果は大きいですよね。
周りの人に聞くと、あんまり賛同してれる人もいない・・・。

あらま、自分は一応やっている派です。
WordではなくWikiですが。

wordを利用した場合の解決策

Wordで履歴管理しようとすると選択肢が限定されてくるように感じます。
思いつくのは、以下の方法(実際に全て検証しているわけではありません)。

  1. Word自身のdiff/履歴管理機能を使う(Diff:ツール→文書の比較と反映)
    • 履歴管理に関しては、Word内部で独自管理されるのでリビジョンの意味がなくなってしまうので、バージョン管理システムと相性が悪いように感じる。
  2. xdocdiffを利用する(Windows限定)
    • ローカルだけではなくTracやRedmineと連携させて、サーバにインストールする方法でも可能だが、Linuxで利用できないのが痛すぎる(Wineでいける?)。
    • メリットとしては、リポジトリの差分参照と同じインターフェイスで参照できるのは非常に便利。
      サーバがWinでTracなりを利用しているなら便利かも
  3. Eclipse3.5のWordの差分表示機能を利用する(ここの下の方で触れられている)。
    • xdocxに対応していないのが痛い。
    • リポジトリ履歴で参照できるかは試していないので知らない。誰か教えて。
  4. SharePointServerを利用する。
    • 出来るらしいが、あんなもの高くて個人レベルや小規模プロジェクトじゃ試せないので、知らない。
  5. Diffdocという有償ツールを利用する
    詳しくは知りません。ウン万円ですがこれを買うなら違うものを買います。
  6. 別のテキスト形式で管理して、必要に応じてExportする。
  7. Silverlight4のCOM連携とかに期待して星を見ながら待つ。

自分の環境の場合

冒頭にあるように、自分の場合は6になります。希望は7ですが。
昔、ちろっと書いたような気がしますが…
実体をWordで管理せずにTracで管理しているのは、自分が求めているドキュメント機能が、

  • ブラウザベースであること(いつでも読める、ハイパーリンクによる遷移、ViewとEditの分断)
  • 複数ページにより構成がしやすい(1つの機能単位で仕様まとめたい場合はsheetによる分割(Excel)や、見出しごとに分割(Word)よりも視認性があがると思います)。
  • ハイライトや強調、イタリック、画像添付などのサポート(tracはドラッグドロップ出来ないなど多少弱い部分もありますが)

といったことから、Wikiで必要十分かなと。
もう少し具体的に言うと、tracのwikiで管理して必要(納品とかですね)に応じてWordやPDFにエクスポートします。
※TracプラグインWikiExportPluginを参照のこと。日本語だとちょっち問題ありますが。

今の運用方法だと、ストーリー(要するに要件)をWiki上に書いて、UI設計のMock(HTMLなので)も

{{{
#!html
}}}

を利用して、Trac上に埋め込みます。
Mockを埋め込むと画面遷移をしながら仕様を詰めて、必要に応じてその場でWikiを修正できるのが非常に助かります。
※hoge.htmlの仕様は、wiki/hoge.htmlという【Wikiページ】に定義されているため、埋め込まれたHTML単位で画面遷移が可能です。

この運用で見えてきた問題点

但し、この運用すると以下のような問題があります。

  • Wiki文法ベースでのDiffになってしまうこと
  • 検索にいらないHTMLタグが無駄に引っかかること。
  • Tracベースの管理ため、仕様の履歴管理(要するにWikiのスナップショット)が出来ない。

まぁ、この辺りはおいおい解決していこうかなと。

以上です。

Posted in program | タグ: , , | Leave a Comment »

agiloをインストールしたら有効化されなくてはまった

Posted by hikaruworld : 2009 12月 9

結論はGenshiのバージョンが古かったこと。

自分の場合、easy_install を利用して全環境に適用可能にするのではなく、
任意の環境のpluginsフォルダにインストールするケースが多い。
理由はいくつかあるが、もっとも大きいのは属性やスコープの違うtracを複数運用しているため。
# 開発用だったり、あるいは運用用だったり、要件管理用だったり。

そんなわけでagilo

python setup.py bdist_egg

でインストール→コピー→プラグイン有効化したわけだが、なぜか画面に表示されない。

agiloのsetup.pyを確認してみたが、必須モジュールのGenshiもsimplejsonもインストールしている。

   install_requires=['trac >= 0.11',
                      'genshi >= 0.5.1, < 0.6dev', # see Genshi bug #254
                      'simplejson'
                      ], 

変だなーと思いつつログを確認してみると、以下のようなエラーが出てる。

2009-12-09 14:38:36,916 Trac[loader] ERROR: Skipping “agilo 0.8.3-r1918-20090925”: (version conflict “(Genshi 0.5 (/usr/local/Python252/lib/python2.5/site-packages/Genshi-0.5-py2.5-linux-i686.egg), Requirement. parse(‘genshi>=0.5.1,<0.6dev'))")

なるほど、つまりGenshiのバージョンが古いと。

easy_installを使ってGenshiのバージョンをUpdateした

easy_install -U Genshi

するとGenshiのバージョン0.5.1がインストールされたのでapache再起動

…今度はInternalServerError….orz.

ExtractionError: Can’t extract file(s) to egg cache\n\nThe following error occurred while trying to extract file(s) to the Python egg\ncache:\n\n [Err no 13]

なんか、懐かしいバグにあったったみたい。
easy_install.pthからGenshiの行を削除してeggファイルを削除して再度Genshiをインストール。

easy_install --always-unzip Genshi

DBをupdate。
OK-。

無事確認できた。
なんかいらん事にはまってしまったorz…

Posted in program | タグ: , | Leave a Comment »

FlashViewプラグインに引数を追加してみた

Posted by hikaruworld : 2009 9月 28

tracでFlashを表示するためのプラグインとしてFlashViewPluginというプラグインがあります。
これは大変便利なのですが、引数として、対象となるswfファイル、幅、高さしか渡せないため、
FlashVarsで引数やquorityを設定できないのでちょっと困るときがあります。ありますよね?

というわけで、このマクロを少し拡張してみました。
やりたいことは以下のとおりです。

  • FlashVarsを渡したい
  • quorityを指定したい(デフォルトはlow)

できるだけ、元ソースに編集を加えない方向で修正してみました。
修正結果のdiffを張っておきます。

diffを適用すれば以下のような感じで利用できるようになります。

[[FlashView(hoge.swf, 400,300,vars="hoge=piyo", quality=hight)]]
変数 内容 補足
第1引数 対象のswfファイル 必須
第2引数 必須?
第3引数 高さ 必須?
keyがvars FlashVarsに渡される引数(ペア値を渡す場合は括弧でくくること) 任意
keyがquality 解像度。デフォルトはlow 任意
*** flashview.py.r2457	2009-09-28 14:27:54.000000000 +0900
--- flashview.py	2009-09-28 14:30:04.000000000 +0900
***************
*** 5,11 ****
  from cgi import escape as escapeHTML
  import os
  from trac.core import *
! from trac.wiki.api import IWikiMacroProvider

  def swfsize(f):
	  magic, version, datasz = unpack("<3s1B1L", f.read(8))
--- 5,11 ----
  from cgi import escape as escapeHTML
  import os
  from trac.core import *
! from trac.wiki.api import IWikiMacroProvider, parse_args

  def swfsize(f):
	  magic, version, datasz = unpack("<3s1B1L", f.read(8))
***************
*** 63,69 ****
		  # args will be null if the macro is called without parenthesis.
		  if not content:
			  return ''
!         args = content.split(',')
		  filespec = args[0]

		  # parse filespec argument to get module and id if contained.
--- 63,70 ----
		  # args will be null if the macro is called without parenthesis.
		  if not content:
			  return ''
!         args, kw = parse_args(content);
!         #args = content.split(',')
		  filespec = args[0]

		  # parse filespec argument to get module and id if contained.
***************
*** 142,151 ****
				  width = args[1]
				  height = args[2]

		  vars = {
			  'width': width,
			  'height': height,
!             'raw_url': raw_url
			  }

		  return """
--- 143,165 ----
				  width = args[1]
				  height = args[2]

+         # Custom Options..
+         if "vars" in kw:
+             vars_val = kw['vars'].strip("\"")
+         else:
+             vars_val = ''
+         if 'quality' in kw:
+             qlt = kw['quality'].strip("\"")
+         else:
+             # default parameter
+             qlt = "low"
+ 
		  vars = {
			  'width': width,
			  'height': height,
!             'raw_url': raw_url,
!             'vars_val': vars_val,
!             'qlt': qlt
			  }

		  return """
***************
*** 153,161 ****
		  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"
		  width="%(width)s" height="%(height)s">
	<param name="movie" value="%(raw_url)s">
!   <param name="quality" value="low">
	<param name="play" value="true">
!   <embed src="%(raw_url)s" quality="low" width="%(width)s" height="%(height)s"
		   type="application/x-shockwave-flash"
		   pluginspage="http://www.macromedia.com/go/getflashplayer">
	</embed>
--- 167,176 ----
		  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"
		  width="%(width)s" height="%(height)s">
	<param name="movie" value="%(raw_url)s">
!   <param name="quality" value="%(qlt)s">
	<param name="play" value="true">
!   <param name="FlashVars" value="%(vars_val)s" />
!   <embed src="%(raw_url)s" quality="%(qlt)s" width="%(width)s" height="%(height)s" FlashVars="%(vars_val)s"
		   type="application/x-shockwave-flash"
		   pluginspage="http://www.macromedia.com/go/getflashplayer">
	</embed>

面白かったのは、trac.wiki.api. parse_argsという関数がめちゃ便利でした。
この関数は、引数に渡されたマクロのパラメータを分解してくれるんですが、
例えば[[Hoge(http://hoge/, 400, piyo=hogepiyo)]]という値の場合

http://hoge/, 400, piyo=hogepiyo

という文字列が渡されてくるのですがparse_argsを使って以下のようにします。
[/sourcecode]
args, kw = parse_args(content);
[/sourceocde]
すると、argsには

list: [u’http://hoge/&#8217;, u’400′]

kwには

dict: {‘piyo’: u’hogepiyo’}

が渡されます。

つまり、argsにはキーを持たない値の一覧、kwにはキーと値のペアを辞書型で渡してくれるという優れものです。
これは面白いので、是非ソースを…と言いたいところですが
これはまた後日tracのソースを読みながら見てみたいと思います(使い方はhelp()で)。

ということをやった後に実は既に対応されている方がいました(SWFObjectの対応に併せて、Flashvarsも渡せるようにしてくれています)。

何が悲しいかといえば、既に自分のプロジェクトでもパッチを適用していたことに後で気がついたことです。
amlineというグラフチャートを利用していたので、SwfObjectも設定されているし。
悲しい…

まぁ、SWFObjectをいちいちヘッダーに埋め込みたくないようなかたがいれば使ってください。

Posted in program | タグ: , , | Leave a Comment »

tracのソースを読む(その1) – Standalone.py –

Posted by hikaruworld : 2009 9月 26

前回のエントリにある通りとりあえず、デバッグ環境は構築出来たので、
どこから読むか迷ったんですが、起動スクリプトからソースを読んでいきたいと思います。
# 全体的なtracのアーキテクチャをまず理解するか、テストソースの方がいいのか迷って…

メモ代わりに書いていますので、間違っている部分など突っ込んでいただけると感謝です。

という訳で、まずはtracの内蔵サーバを利用して起動させる際に利用されるStandalone.pyから見ていこうと思います。
今回読んだソースはL296-L298のたった3行のみです(涙)
# のわりには、めちゃ長文なんですが(汗

ここで起動スクリプトがstandalone.pyであると知っているのは、公式のドキュメントにそう書いてあるからです。
あ、言い忘れましたがTracのバージョンは0.11.5になります。

さて、起動部分からです。
standalone.pyは基本的にはクラス(class)と関数(def)のみで、実際の実行は最後尾の以下のみになります。

if __name__ == '__main__':
	pkg_resources.require('Trac==%s' % VERSION)
	main()

速攻まずここで躓きました。
よくわからなかったのは以下の通り(ほとんどわかっていないんです)。

  1. __name__とは何か
  2. pkg_resourcesとは何か
  3. pkg_resources.requireとは何か

1. __name__とは何か

pythonはスクリプトとして実行した場合(コンソール上からpython standalone.pyとかやる)は__name____main__という文字列が
割り当てられるということは知っていましたが、実際に細かい挙動がわからなかったので復習しておくことにしました。
へたれプログラマの日々というサイトがわかりやすくて参考になりました。感謝。

といわけで上記サイトを参考に早速実験してみます。
カレントディレクトリにHoge.pyというファイルを作成します。中身は以下の通りです。

#!/usr/bin/python

print "hoge";
print __name__;

if __name__ == '__main__':
	print 'oooo....'

これをコンソール上から実行してみます。

python Hoge.py

hoge
__main__
oooooo…..

書いてある通り、__name__には__main__という文字列が格納されているようです。
__name__に設定されている文字列も正しかったためif文内部の実行も行われています。

では今度は、インタプリタ上で実行してみます

import Hoge

hoge
Hoge

ふむふむ。importした際のクラス名が__name__に格納されていますね。
そして当然if文内部は実行されていません。

では、今度はエイリアスをつけてみます。

import Hoge as piyo

こちらでもエイリアスが設定される訳ではなく、importの実体が設定されるため変わらないようです。

hoge
Hoge

やはり参考にしたサイトでも示されていた通りの挙動を示すようですね。

今回参照しているStandalone.pyはスクリプトとして実行された際に特別な挙動で動くように設定されていましたが、
その他の方法としては、これらの処理はdoctestを実行する際に便利に利用できるようです。

2. pkg_resourcesとは何か

次に気になったのは、以下です。

pkg_resources.require('Trac==%s' % VERSION)

2-1. ‘Trac==%s’ % VERSIONとは何か

とりあえず細かく分解して確認していきたいと思います。
%sをVERSIONで置換している事はわかりますが、VERSIONの取得がどうなっているか気になりました。
VERSION自体はimport時にエイリアスとして設定されており、実際はtracパッケージのパッケージ変数を参照しています(import文を参照)
Pythonはas演算子を使ってimportした関数やクラスを任意の文字列に置き換える事が出来るそうです。

from trac import __version__ as VERSION

from tracとfromにパッケージを指定することで、__init__.py上に設定されている変数が参照可能になります。

2-1-1. __init__.pyとは

__init__.pyはpythonのサブディレクトリを示す際に必要となるファイルです。
pythonランタイムによって対象のディレクトリがサブパッケージと認識させるためにはこのファイルを必ず置いておく必要があるそうです。
この名前のファイルが置いてあること」が重要で、ファイルの中身は空でもかまいません。

ただ、今回のように__init__.pyに変数が設定されているような場合、__init__.pyで定義されているファイルを読み込みたい場合は、
fromでパッケージを指定して、「package名.initに存在する変数」で参照することが可能になります。
というわけで、__init__.pyの中身を参照してみます。

__version__ = __import__('pkg_resources').get_distribution('Trac').version
2-1-1-1. __import__とは

__import__はPythonによって提供されている組み込み関数です。
余談ですが、Python上で「__」(アンダースコア2つ)によって定義される関数は特別な意味を持つそうです。

__import__はimportによって任意のオブジェクトをimportした際に呼び出される組み込み関数になります。
そのため、以下お処理は同じ物を表していいます。

# __import__とimportは同じ処理をしている
__import__('pkg_resources')
import pkg_resources
2-1-1-2. pkg_resources.get_distributionとは

get_distributionはsetuptoolsによって提供される関数で、get_distributionの引数で指定したモジュール名をキーとしてDistributionを返します。
これはTracがPythonモジュールの配布の方式で配布されているため、Distributionからバージョン情報が取得できるようになるためのようです。

ここでは単純にversion情報の取得のみ行っていますが、以下のような情報も参照可能なようです。
詳しくはDistributionのインスタンスを引数にhelp()を実行してみると色々と出てくると思います。

>>> __import__('pkg_resources').get_distribution('Trac').key
>>> __import__('pkg_resources').get_distribution('Trac').extras

なお、これらのDistributionとしての設定はインストール時のsetup.pyのsetup()に記述されています。
setup()で引数に取れるデフォルトのプロパティは、distutils.core — Distutils のコア機能を、setuptoolsによって拡張されるプロパティはNew and Changed setup() Keywords(邦訳)を参照してください。
どうせなのでpythonのsetup.pyを確認してみます(maintainerなどが書いてあるためtrac0.11.1-ja1を表示しています)。

from setuptools import setup, find_packages

setup(
	# パッケージの名前
	name = 'Trac',
	# パッケージのバージョン番号
	version = '0.11.1.ja1',
	# 1行で書いたパッケージ解説
	description = 'Integrated SCM, wiki, issue tracker and project environment',
	# パッケージの長い解説
	long_description = """
Trac is a minimalistic web-based software project management and bug/issue
tracking system. It provides an interface to the Subversion revision control
systems, an integrated wiki, flexible issue tracking and convenient report
facilities.

Japanese translated edition.
""",
	# パッケージ作者の名前
	author = 'Edgewall Software',
	# パッケージ作者のemailアドレス
	author_email = 'info@edgewall.com',
	# 現在のメンテナの名前(パッケージ作者と異なる場合)
	maintainer = 'InterAct',
	# 現在のメンテナのemailアドレス(パッケージ作者と異なる場合)
	maintainer_email = 'trac-ja@i-act.co.jp',
	# パッケージのライセンス
	license = 'BSD',
	# パッケージのURL(ホームページ)
	url = 'http://trac.edgewall.org/',
	# パッケージダウンロード用URL
	download_url = 'http://trac.edgewall.org/wiki/TracDownload',
	# パッケージのカテゴリのリスト
	# 詳細は右記 http://pypi.python.org/pypi?:action=list_classifiers
	classifiers = [
		'Environment :: Web Environment',
		'Framework :: Trac',
		'Intended Audience :: Developers',
		'License :: OSI Approved :: BSD License',
		'Operating System :: OS Independent',
		'Programming Language :: Python',
		'Topic :: Software Development :: Bug Tracking',
		'Topic :: Software Development :: Version Control',
	],
	# distutilsが操作するPythonパッケージのリスト
	packages = find_packages(exclude=['*.tests']),
	# パッケージ名と、ファイル名のパターンのリストの対応付け
	package_data = {
		'': ['templates/*'],
		'trac': ['htdocs/*.*', 'htdocs/README', 'htdocs/js/*', 'htdocs/css/*',
				 'htdocs/guide/*'],
		'trac.wiki': ['default-pages/*'],
		'trac.ticket': ['workflows/*.ini'],
	},
	# この引数を指定すると、例えばsetup.py testを使って、指定されたテストスイートをtestコマンドで実行することが可能
	test_suite = 'trac.test.suite',
	# プロジェクトがzipファイルから安全にインストールされ、実行されるか指定します???
	zip_safe = False,

	# この配布物がインストールされるときに、インストールされていなければならない他の配布物を指定
	install_requires = [
		'setuptools>=0.6b1',
		'Genshi>=0.5'
	],
	# 拡張機能を使うためにインストールされていなければならない他の配布物を示す文字列か文字列のリストを対応付ける辞書
	extras_require = {
		'Pygments': ['Pygments>=0.6'],
		'reST': ['docutils>=0.3'],
		'SilverCity': ['SilverCity>=0.9.4'],
		'Textile': ['textile>=2.0'],
	},
	# エントリーポイントのグループ名と、エントリーポイントを定義する文字列または文字列のリストを対応付ける辞書です。
	# エントリーポイントは、プロジェクトが提供するサービスまたはプラグインを動的に探す手助けをします。
	entry_points = """
		[console_scripts]
		trac-admin = trac.admin.console:run
		tracd = trac.web.standalone:main

		[trac.plugins]
		trac.about = trac.about
		trac.admin.console = trac.admin.console
		trac.admin.web_ui = trac.admin.web_ui
		trac.attachment = trac.attachment
		trac.db.mysql = trac.db.mysql_backend
		trac.db.postgres = trac.db.postgres_backend
		trac.db.sqlite = trac.db.sqlite_backend
		trac.mimeview.enscript = trac.mimeview.enscript
		trac.mimeview.patch = trac.mimeview.patch
		trac.mimeview.php = trac.mimeview.php
		trac.mimeview.pygments = trac.mimeview.pygments[Pygments]
		trac.mimeview.rst = trac.mimeview.rst[reST]
		trac.mimeview.silvercity = trac.mimeview.silvercity[SilverCity]
		trac.mimeview.txtl = trac.mimeview.txtl[Textile]
		trac.prefs = trac.prefs.web_ui
		trac.search = trac.search.web_ui
		trac.ticket.admin = trac.ticket.admin
		trac.ticket.query = trac.ticket.query
		trac.ticket.report = trac.ticket.report
		trac.ticket.roadmap = trac.ticket.roadmap
		trac.ticket.web_ui = trac.ticket.web_ui
		trac.timeline = trac.timeline.web_ui
		trac.versioncontrol.svn_fs = trac.versioncontrol.svn_fs
		trac.versioncontrol.web_ui = trac.versioncontrol.web_ui
		trac.web.auth = trac.web.auth
		trac.wiki.macros = trac.wiki.macros
		trac.wiki.web_ui = trac.wiki.web_ui
	""",
)

これらの設定はEgg化した際に、EGG-INFO内に格納されるようですが、
今はTracのソースを読んでいるのでsetuptoolsについては深追いしません。
出来れば、この辺りは一度きちんとドキュメントをしっかり読んでおきたいところです。

今回はget_distributionのメソッドの内部までは踏み入りませんので、ソースのコメントだけ見てみます。
引数で渡された情報を元に合致するDistributionオブジェクトを返しているようですね(ソースは変数は省略)。
DistributionObjectを探

"""Return a current distribution object for a Requirement or string"""

3. pkg_resources.requireとは何か

pkg_resourcesはファイルの冒頭で以下の様にimportされています。

import pkg_resources

pkg_resourcesはsetuptoolsで定義されたモジュールで、setuptoolsはPythonのdistutilsの多くの機能が拡張されたものだそうです。
distutilsとはPythonモジュールの配布の形式で、俗に言う

python setup.py insatll 

でのインストールが可能になるための方法になります。

pkg_resourcesに関してはなんとなくわかったような気がするので(というか深追いするときりがない)
その関数であるrequireの実装がどうなっているかだけ覗いてみました。

	def require(self, *requirements):
		"""Ensure that distributions matching `requirements` are activated

		`requirements` must be a string or a (possibly-nested) sequence
		thereof, specifying the distributions and versions required.  The
		return value is a sequence of the distributions that needed to be
		activated to fulfill the requirements; all relevant distributions are
		included, even if they were already activated in this working set.
		"""

		needed = self.resolve(parse_requirements(requirements))

		for dist in needed:
			self.add(dist)

		return needed

コメントで丁寧に説明されていますが、引数で指定したrequirementsに関連するモジュールを取得しているようですね。
self.resolveで必要なDistributionの配列を返しています。

ちょっと面白かったのは、requireの引数にはバージョン番号の指定が必須になっているところです。
バージョン管理が意識されているなぁと感じます。

あと、ソースの内部を覗いているとresolve内部でリストに対して以下のような処理を行っている部分がありました。

hoge[::-1]

???だったんですが、つぶやいてみると以下のように教えてくれた方がいて納得しました(@miau_jp, @nishio に感謝!)

@hikaruworld pythonでlist[::1]とかlist[::-1]っていう書き方を見るんだけど、これはどう解釈するんだろう .
@miaumiau_jp @hikaruworld スライスの step 指定だとは思いますけど、1 なら省略可能なような・・・。
@nishio @hikaruworld 3番目はstepなので’abc'[::-1]==’cba’で’abcdefg'[::2]==’aceg’

つまり…

# [::x]のxは実行するステップ単位を表す
# [::]と[::1]は同じ。
>>> hoge = 'abcdefgh'
>>> hoge[::1]
'abcdefgh'
# 逆順
>>> hoge[::1]
'hgfedcab'
# 2つ単位で
>>> hoge[::2]
'aceg'

ということらしいです。この書き方は新鮮で面白いです。
テキストスライスに関してはこの辺りが面白かったです。

今回ははじめの一歩という事で。
これから起動部分のmain()関数に入っていきたいと思います。
その際にtracdからどうやってstandalone.pyが実行されるのかも確認していきたいと思います。

残件

以下は、今回調べきれなかった残件になります。

  • setuptoolsによる挙動の詳細(インストール周りなど)
  • doctestとdocstringの使い方

Posted in program | タグ: , , | Leave a Comment »

Pythonの勉強のためにTracのデバッグ環境を構築する

Posted by hikaruworld : 2009 9月 21

おそらく他人が読んでもわからないでしょう…

と、前置きしつつ。
Pythonの勉強をしたいなぁと常日頃思っていて、
何かいい例がないかなぁと思っていました。

よく考えれば日頃愛用しているtracがpython製だったのを思い出したので、
これを解析しながら勉強して見ようと思い立った次第です。

とりあえず、静的解析は難しいので動的解析をしようと思い、
pyDev上にtracのデバッグ環境を構築した際のメモになります。

前提条件

  • tracdで起動する→standalone.pyを直接起動することにしました
  • trac用に別のPythonをインストール
  • Subversionのインストールは不要

インストール構成は以下の通り。pythonを別にインストールしている。
なおインストール場所は/dev/以下とする。

.
|-- bin					--- スクリプト格納用(trac-adminなど)
|-- data				--- tracプロジェクト
|-- pyDev				--- IDEを利用
|-- python252			--- Python本体。この配下にTracがインストールされる
|   |-- bin
|   `-- lib
|       `-- python2.5
|           `-- site-packages
                `-- Trac-0.11.5-py2.5.egg
`-- workspace			--- pyDevの作業用スペース

tracのインストール

詳しい方法は省きますが、今回は必要最低限のモジュールだけでよいので、
easy_instlalで行い、tracと(その依存関係にある)Genshiをあわせてインストールします。
日本語版を適用するためtracをアンインストールして、trac-jaをインストールします。

その後、tracのsampleプロジェクトを作成します。

注意点

すっかり忘れていたんですが、MacでTrac環境を構築するとX-MAC-JAPANESEという
エンコードをPythonが参照できないLookupErrorが発生します。

基本的にはエラーが発生する箇所のエンコードの設定を修正すればよいんですが(対処療法です)、
この件を忘れていてはまりました。
以前この件ではまったときはtrac/util/datefmt.pyだったように記憶しているのですが、
今回は、trac-adminによるスクリプト実行時でconsole.pyでエラーが発生していました

pyDev上にプロジェクトを作成

個人的には、ここを忘れないようにメモしています。
なお、pyDevのインストールに関しては省略ということで。

環境設定

環境設定→PyDev→インタープリタPythonが/dev/python252/bin/pythonを向いていること。
向いていなければ新規追加する。

Tracプロジェクトの作成

  1. プロジェクト→PyDev
  2. プロジェクト名 — trac
  3. デフォルトのチェックを外す
  4. プロジェクト・コンテンツ — /dev/python252/lib/python2.5/site-package/Trac-0.11.5-py.2.5.egg
  5. 文法バージョン — 2.5
  6. インタープリタ — 上記環境設定で設定したインストールディレクトリ
  7. デフォルト:ソースディレクトリを… — チェックをはずす

[TODO Image]

スタンドアローン起動の設定

Tracは内部にスタンドアローン起動用のサーバを持っているのでそれを利用します。
Tracdを外部からたたく必要があるかと思ったら、いつの間に準備されていてびっくりしました。

  1. trac/util/webへ
  2. standalone.pyを右クリックして「デバッグ」→「python実行」
  3. こんな感じで怒られる。

    pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)
    pydev debugger: starting
    Usage: standalone.py [options] [projenv] …

    standalone.py: error: either the –env-parent-dir option or at least one environment must be specified

  4. 右クリック→デバッグ構成を選択
  5. 先ほど実行したstandalone.pyが設定されているはずなので、こいつの設定を修正する
    • 引数(プログラムの引数) — -p 8080 /dev/data/sample
    • インタープリタ(インタープリター) — 環境設定で設定したPython
  6. 起動ログが出力される。

    pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)
    pydev debugger: starting
    Server starting in PID 409.
    Serving on 0.0.0.0:8080 view at http://127.0.0.1:8080/

これでデバッグ可能に成ります。

Posted in program | タグ: , , , | Leave a Comment »

TicketBox導入メモ

Posted by hikaruworld : 2009 9月 18

Topページに特定条件のチケット一覧を表示したく、何かいいものがないかなぁと探していると、
TicketBox.pyというマクロがいいよと@Ryuzeeさんのところで紹介されていたので、
ちょっくら試してみることにしました。

インストールの過程で少しはまったのでメモしておきます。

とりあえず、MacroなのでTrac-HacksTicketBoxMacro
最新リビジョン(rev:5658)を落としてきてTRAC_ROOT/plugins以下に配備しました。
ちなみにtracのバージョンはTrac-0.11.1.ja1になります。

その後、お決まりのごとくApacheを再起動します。
ところがなぜか、Adminの管理画面でもマクロが有効化されておらず、設定も反映されていないようです。
というわけで、とりあえずログを覗いてみると、こんなエラーが出ていました。

2009-09-17 10:58:43,806 Trac[loader] ERROR: Failed to load plugin from /hoge/hoge/trac/plugins/TicketBox.py
Traceback (most recent call last):
File “/usr/local/python252/lib/python2.5/site-packages/Trac-0.11.1.ja1-py2.5.egg/trac/loader.py”, line 89, in _load_py_files
module = imp.load_source(plugin_name, plugin_file)
File “/mnt/raid/source/data/trac/pma-opration/plugins/TicketBox.py”, line 65, in
ver = [int(x) for x in verstr.split(“.”)]
ValueError: invalid literal for int() with base 10: ”

イテレータをまわしているところで落ちているようです。
ちょっとソースを覗いて見ます(こういうときマクロだと確認しやすくて楽でよいですね)。

63行目辺りは以下のようになっていました。

# get trac version
verstr = re.compile('([0-9.]+).*').match(version).group(1)
ver = [int(x) for x in verstr.split(".")]
[/soureccode]
65行目は以下の通りです。
[soureccode language="python"]
ver = [int(x) for x in verstr.split(".")]

おそらくint()へのキャストの部分で落ちていることが推測されます。
63行目で渡されるversionの値を確認してみると、

– 0.11.1.ja1

になっていました。

…いや、まぁね。
re.compileでマッチングさせてその後にsplitで分割させているようですが、これが原因で落ちているようです。
この正規表現コンパイルだと最後に空白値が渡されて、その空白値をintでキャストしようとしていますね…
日本語ローカライズされているtracはバージョンの振り方が公式のものに対して、最後のjaXが付与されているのが問題になっているようです。

ためしに、英語版のtrac0.11.5に対して実行してみたところ問題なく実行されることが確認できました。

というわけで、対処療法として、キャストする前にチェックするようにソースを修正しておきました。
(正規表現を直せといわれそうですが…)

ver = [int(0 if x == "" else x) for x in verstr.split(".")]

OK-。
なんというか、Pythonの三項演算子は気持ち悪いですね。。。。

Posted in program | タグ: , , | Leave a Comment »

RHEL4にGraphvizの導入する

Posted by hikaruworld : 2008 12月 9

Graphviz をRHEL4にインストールする際の導入に関しての備忘録。

インストール

Trac0.11のチケットのワークフローをカスタマイズする必要があった。
それに関連して、後々確認しやすいようにgraphvizのインストールも行う。

  1. ここからRPMをダウンロードし、rpmコマンドでインストール(コマンドは省略)。

動作確認

Graphviz チュートリアル を参考に、簡単なサンプルを動かしてみる。

  1. sample.dotというファイルを作成して以下を書く。

    digraph sample {
    alpha -> beta;
    alpha -> gamma;
    beta -> delta;
    }

  2. コマンドラインで以下を実行する(RPMインストールなのでパスは通っていることが前提)。

    dot -Tgif sample1.dot -o sample1.gif

トラブルシューティング

Format: “XXX” not recognized.

フォーマットエラーで以下のようなエラーが発生する。

Format: “gif” not recognized. Use one of: canon cmap cmapx cmapx_np dia dot eps fig hpgl imap imap_np ismap mif mp pcl pic plain plain-ext ps ps2 svg svgz tk vml vmlz vtx xdot

ここ と同じようにgraphviz-gdをインストールする事で対応可能。

user gviz does not exist – using root

ユーザが存在しないエラー?

RPMインストール中に発生した。以下はログ。

Preparing… ########################################### [100%]
1:graphviz-gd 警告: user gviz does not exist – using root
警告: group gviz does not exist – using root
警告: user gviz does not exist – using root
警告: group gviz does not exist – using root
########################################### [100%]

警告のようだし、using rootといっているので無視する。原因は未調査。

Error: Could not find/open font

フォント参照エラーのようで、以下のようなエラーが出る。
一応画像は出力されており参照も可能だが、日本語が文字化けするみたいだ。

Error: Could not find/open font

ここ を参考に修正してみる。
フォントが参照できてい状態なので、一番強引な方法ではあるが、fontnameにフォントファイルのパスを指定した。
fontpathの設定ではなんだかうまく行かなかった。

digraph sample {
node [fontname=”/usr/share/fonts/ja/TrueType/kochi-gothic-subst.ttf”];
alpha -> beta;
alpha -> gamma;
beta -> あいうえお;
}

OK.

TracWorkFlowsとGraphviz

TracのTracWorkflowはGraphvizを用いて書き出すスクリプトが準備されている。

詳細はかおるんダイアリーが詳しい。
ここでは簡単な手順のみ。

  1. workflow_parser.pyを探す。
    • ソースからTracをインストールした場合は、%TRAC_SRC%/contrib/workflow/workflow_paser.py にあるはず
  2. workflow_pyser.pyを実行時に出力したいプロジェクトのtrac.iniを指定してGraphvizのworkflow.dotに書き出す。

    python workflow_parser.py trac.ini > workflow.dot

  3. 後は、いつものごとく以下のような感じで書き出す。

    dot -Tpng workflow.dot > workflow.png

Posted in server | タグ: , , | Leave a Comment »