以前紹介した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というファイルを作成します。典型的には以下の様になります。

PYTHON:
  1. from __future__ import with_statement
  2. from tasktools import *
  3.  
  4. global_description(u"""
  5. サンプルタスクファイルです。
  6. """)
  7.  
  8. use_without_standard() # distutilsの標準コマンドを使用しないことを宣言します。
  9. load_path("./tasks") # "./tasks"以下のtasks.pyを再帰的に読み込みます
  10.  
  11.  
  12. with 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.  
  38. if __name__ == "__main__":
  39.   run()


ではpython tasks.py --help-commandsと実行してみましょう

############################################################

サンプルタスクファイルです。

############################################################

Commands:
  file:init        ファイルを初期化します。
        sub commands:
                file:mktmpfile
                file:mklogfile
  file:mklogfile   ログファイルを作成します。
  file:mktmpfile   一時ファイルを作成します。

usage: tasks.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
  or: tasks.py --help [cmd1 cmd2 ...]
  or: tasks.py --help-commands
  or: tasks.py cmd --help

この様にglobal_descriptionで設定した説明と、定義したタスクの一覧が表示されます。

次に./tasks/tasks.pyを作成してみます。

PYTHON:
  1. from __future__ import with_statement
  2. from tasktools import *
  3.  
  4. use_without_standard()
  5. with namespace("subs") as ns:
  6.   class test1(Task):
  7.     u"""サブディレクトリで定義されたタスクです
  8.     """
  9.     def run(self):
  10.       print "sub test"
  11.  
  12. if __name__ == "__main__":
  13.   run()


このファイルは./tasks.pyload_path("./tasks")と宣言しているので./tasks.pyを実行すると自動的に読み込まれます。 もう一度python tasks.py --help-commandsと実行してみましょう

############################################################

サンプルタスクファイルです。

############################################################

Commands:
  file:init        ファイルを初期化します。
        sub commands:
                file:mktmpfile
                file:mklogfile
  file:mklogfile   ログファイルを作成します。
  file:mktmpfile   一時ファイルを作成します。
  subs:test1       サブディレクトリで定義されたタスクです

usage: tasks.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
  or: tasks.py --help [cmd1 cmd2 ...]
  or: tasks.py --help-commands
  or: tasks.py cmd --help

確かにsubs:test1コマンドが追加されています。

ではタスクを実行してみましょう。python tasks.py file:initを実行してみます。

running file:init
running file:mktmpfile
create /tmp/tmp.txt
running file:mklogfile
create log file

おお、実行されましたね。

user_optionsを定義しているタスクではオプションも渡せます。python tasks.py file:mktmpfile --path=/tmp/change.txtを実行してみましょう。

running file:mktmpfile
create /tmp/change.txt

ちゃんとオプションが渡されていますね。

 
 


 
こんな感じです。distutilsの独自コマンドに関する説明は46 新しいDistutilsコマンドの作成を参照してください。正直使えないページですが・・・。一応説明しておくとinitialize_optionsはuser_optionsの定義から自動生成するようになっています。またdistutils.core.Commandを継承しているのでこのクラスの機能も使えます。

せっかくCodereposに突っ込んだのでバグなんかが見つかったらガンガン直しちゃってください。