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

from __future__ import with_statement
from tasktools import *

global_description(u"""
サンプルタスクファイルです。
""")

use_without_standard() # distutilsの標準コマンドを使用しないことを宣言します。
load_path("./tasks") # "./tasks"以下のtasks.pyを再帰的に読み込みます


with namespace("file") as ns:
  class mktmpfile(Task):
    u"""一時ファイルを作成します。
    """
    user_options = [("path=", "p", u"作成するパスです")]
    def run(self):
      print "create %s"%self.path

    def finalize_options(self):
      if not self.path: self.path = "/tmp/tmp.txt"

  class mklogfile(Task):
    u"""ログファイルを作成します。
    """
    def run(self):
      print "create log file"

  class init(Task):
    u"""ファイルを初期化します。
    """
    def run(self):
      pass

    sub_commands = [("file:mktmpfile", None),
                    ("file:mklogfile", None)]

if __name__ == "__main__":
  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 を作成してみます。

from __future__ import with_statement
from tasktools import *

use_without_standard()
with namespace("subs") as ns:
  class test1(Task):
    u"""サブディレクトリで定義されたタスクです
    """
    def run(self):
      print "sub test"

if __name__ == "__main__":
  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に突っ込んだのでバグなんかが見つかったらガンガン直しちゃってください。

comments powered by Disqus