以前紹介したPython版Rakeもどき を改良してCodeReposに突っ込みました。まだ100行くらいです。自分では一番使っている自作モジュールなのでそろそろまとめようと思っていたのです。
http://coderepos.org/share/browser/lang/python/tasktools/trunk/tasktools.py
改良点
setuptools
があるときはそっちを使うようにした。use_without_standard
メソッドによってdistutils
標準タスクを消すことができる。これによって--help-commands
の画面がすっきりする。また、この場合名前空間のセパレータに:
を用いるようになった。global_description
によってタスクファイル自体に説明がつけられるようになった。load_path
メソッドで指定したディレクトリ以下を再帰的に検索し「tasks.py
」という名前のファイルを読み込むことができるようになった。--help-commands
で表示されるコマンドの並び順をソートするようにした。--help-commands
でサブコマンドを一覧表示するようにした。
使用方法
以前書いたのとほとんど同じなんですが、まとめなおしておきます。
tasktoolsとは?
distutils
および setuptools
を拡張してextra commandを簡単に作成するためのユーティリティです。RubyにおけるRakeのようなものです。ビルド機能がほしい場合は distutils
, setuptools
の標準ビルド機能、もしくは SCons
と組み合わせるとハッピーになれます。
ちなみに、 tasktools
というのは同じく distutils
の拡張である setuptools
の命名規則に習っています。 task
機能を強化するから tasktools
です。
チュートリアル
典型的な tasktools
の使い方です。
まず tasks.py
というファイルを作成します。典型的には以下の様になります。
1from __future__ import with_statement
2from tasktools import *
3
4global_description(u"""
5サンプルタスクファイルです。
6""")
7
8use_without_standard() # distutilsの標準コマンドを使用しないことを宣言します。
9load_path("./tasks") # "./tasks"以下のtasks.pyを再帰的に読み込みます
10
11
12with namespace("file") as ns:
13 class mktmpfile(Task):
14 u"""一時ファイルを作成します。
15 """
16 user_options = [("path=", "p", u"作成するパスです")]
17 def run(self):
18 print "create %s"%self.path
19
20 def finalize_options(self):
21 if not self.path: self.path = "/tmp/tmp.txt"
22
23 class mklogfile(Task):
24 u"""ログファイルを作成します。
25 """
26 def run(self):
27 print "create log file"
28
29 class init(Task):
30 u"""ファイルを初期化します。
31 """
32 def run(self):
33 pass
34
35 sub_commands = [("file:mktmpfile", None),
36 ("file:mklogfile", None)]
37
38if __name__ == "__main__":
39 run()
では python tasks.py --help-commands
と実行してみましょう
1############################################################
2
3サンプルタスクファイルです。
4
5############################################################
6
7Commands:
8 file:init ファイルを初期化します。
9 sub commands:
10 file:mktmpfile
11 file:mklogfile
12 file:mklogfile ログファイルを作成します。
13 file:mktmpfile 一時ファイルを作成します。
14
15usage: tasks.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
16 or: tasks.py --help [cmd1 cmd2 ...]
17 or: tasks.py --help-commands
18 or: tasks.py cmd --help
この様に global_description
で設定した説明と、定義したタスクの一覧が表示されます。
次に ./tasks/tasks.py
を作成してみます。
1from __future__ import with_statement
2from tasktools import *
3
4use_without_standard()
5with namespace("subs") as ns:
6 class test1(Task):
7 u"""サブディレクトリで定義されたタスクです
8 """
9 def run(self):
10 print "sub test"
11
12if __name__ == "__main__":
13 run()
このファイルは ./tasks.py
で load_path("./tasks")
と宣言しているので ./tasks.py
を実行すると自動的に読み込まれます。 もう一度 python tasks.py --help-commands
と実行してみましょう
1############################################################
2
3サンプルタスクファイルです。
4
5############################################################
6
7Commands:
8 file:init ファイルを初期化します。
9 sub commands:
10 file:mktmpfile
11 file:mklogfile
12 file:mklogfile ログファイルを作成します。
13 file:mktmpfile 一時ファイルを作成します。
14 subs:test1 サブディレクトリで定義されたタスクです
15
16usage: tasks.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
17 or: tasks.py --help [cmd1 cmd2 ...]
18 or: tasks.py --help-commands
19 or: tasks.py cmd --help
確かに subs:test1
コマンドが追加されています。
ではタスクを実行してみましょう。 python tasks.py file:init
を実行してみます。
1running file:init
2running file:mktmpfile
3create /tmp/tmp.txt
4running file:mklogfile
5create log file
おお、実行されましたね。
user_optionsを定義しているタスクではオプションも渡せます。 python tasks.py file:mktmpfile --path=/tmp/change.txt
を実行してみましょう。
1running file:mktmpfile
2create /tmp/change.txt
ちゃんとオプションが渡されていますね。
こんな感じです。distutilsの独自コマンドに関する説明は 46 新しいDistutilsコマンドの作成 を参照してください。正直使えないページですが・・・。一応説明しておくとinitialize_optionsはuser_optionsの定義から自動生成するようになっています。また distutils.core.Command
を継承しているのでこのクラスの機能も使えます。
せっかくCodereposに突っ込んだのでバグなんかが見つかったらガンガン直しちゃってください。