Python版Rake「tasktools」をCodeReposにコミットした

以前紹介した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 code
  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()
  40.  

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

 code
  1. ############################################################
  2.  
  3. サンプルタスクファイルです。
  4.  
  5. ############################################################
  6.  
  7. Commands:
  8.   file:init ファイルを初期化します。
  9.         sub commands:
  10.                 file:mktmpfile
  11.                 file:mklogfile
  12.   file:mklogfile ログファイルを作成します。
  13.   file:mktmpfile 一時ファイルを作成します。
  14.  
  15. usage: 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
  19.  

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

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

python code
  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()
  14.  

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

 code
  1. ############################################################
  2.  
  3. サンプルタスクファイルです。
  4.  
  5. ############################################################
  6.  
  7. Commands:
  8.   file:init ファイルを初期化します。
  9.         sub commands:
  10.                 file:mktmpfile
  11.                 file:mklogfile
  12.   file:mklogfile ログファイルを作成します。
  13.   file:mktmpfile 一時ファイルを作成します。
  14.   subs:test1 サブディレクトリで定義されたタスクです
  15.  
  16. usage: 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
  20.  

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

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

 code
  1. running file:init
  2. running file:mktmpfile
  3. create /tmp/tmp.txt
  4. running file:mklogfile
  5. create log file
  6.  

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

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

 code
  1. running file:mktmpfile
  2. create /tmp/change.txt
  3.  

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


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

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

07.27.08/12am

About

Author:yuin(http://inforno.net/)

文学部文化学科卒という生粋の文系趣味プログラマ。

主にRuby、Javascript、PHP、JAVA,Python,C,Scala,Schemeなどを使っています。今はPythonな感じかもしれない。今後作曲活動なども復活するかもしれない。

Pages