徹底的に pavement.py

Paver は作業を行うために宣言型/命令型のハイブリッドシステムになるように意図されて作られています。pavement.py のオプションを通して定義することができます。そして、実際、多くのプロジェクトは pavement.py にオプションがありますが何もせずに使用します。例えば Paver 自身の pavement ファイル初期バージョンを考えてみてください。

from paver.easy import *
import paver.doctools

options(
    setup=dict(
    name='paver',
    version="0.3",
    description='Python build tool',
    author='Kevin Dangoor',
    author_email='dangoor+paver@gmail.com',
    #url='',
    packages=['paver'],
    package_data=setuputils.find_package_data("paver", package="paver",
                                            only_in_packages=False),
    install_requires=[],
    test_suite='nose.collector',
    zip_safe=False,
    entry_points="""
    [console_scripts]
    paver = paver.command:main
    """,
    ),

    sphinx=Bunch(
        builddir="build",
        sourcedir="source"
    )

)

@task
@needs('paver.doctools.html')
def html():
    """Build Paver's documentation and install it into paver/docs"""
    builtdocs = path("docs") / options.sphinx.builddir / "html"
    destdir = path("paver") / "docs"
    destdir.rmtree()
    builtdocs.move(destdir)

このファイルは宣言型と命令型両方の様相を持っています。そのオプションは distutils, setuptools や Sphinx がそれぞれのジョブを行うために十分な情報を定義します。これはタスクを定義することを必要とせず実際に機能します。

しかし、Paver の ‘paverdoc’ ビルトインタスクが動作するために Paver のパッケージツリー内部に Sphinx が生成した HTML が必要になります。そのため、生成された HTML ファイルを移動するために html タスクを上書きします。

タスクを定義する

タスクは単純なただの関数です。@task デコレータを使用してタスクとしての関数を指定します。

さらにあるタスクが他のタスクの実行に依存するときは最初に @needs デコレータを指定することもできます。そのタスクは他のタスクのための依存関係として同時に実行されます。

手動でタスクを呼び出す

時々、他のタスクを実行する 前に 何かを行う必要があります。そのため @needs デコレータはそのジョブを実行できません。

もちろん、タスクはただの Python 関数です。そのため、関数呼び出しのように他のタスクを実際に呼び出すこともできます!

どのようにタスク名が動作するか

タスクは長い名前と短い名前の両方を持ちます。短い名前は実際の関数の名前です。長い名前は Python の関数オブジェクトの省略されていない名前です。

例えば、Sphinx は “html” というタスク機能をサポートします。そのタスクの長い名前は “paver.doctools.html” です。

pavement.py で `import paver.doctools` する場合、”html” を参照するためにどちらの名前でも使用できます。

pavement.py で定義したタスクは短い名前でいつでも利用できます。そのタスクは同じ短い名前を使用する他のタスクと競合しない限りどこででも定義されます。

タスクは長い名前で明示的に利用することもできます。

タスクパラメータ

タスクはどんなパラメータも持つ必要はありません。しかし、Paver は適切なクリーン、globals-free な方法(*)で動作するのを許容します。一般的に言うと paver を実行する最も簡単な方法は from paver.easy import * を行うだけです。しかし、あなたが名前空間を多く持つことを好まないなら、関数内に送られた tasks.environment の属性を持つことができます。例えば、次の通りです。

@task
def my_task(options, info):
    # このタスクはオプションを取得して "info" ロギング関数へ送る
    pass

(*): tasks.environment がグローバルです

コマンドライン引数

タスクは他の2つのデコレータを通してコマンドライン引数を受け取るように指定することができます。 @consume_args デコレータは Paver にこのタスク名に続く 全て のコマンドライン引数を伝えます。 options.args か、関数へのパラメータとして args を指定するかのどちらでもその引数を見つけることができます。例えば Paver の “help” タスクは次のように定義されます。

@task
@consume_args
def help(args, help_function):
    pass

“args” パラメータは tasks.environment の属性です(help_function そのまま)。そのため、前のセクションで説明した同じルールを使用して渡されます。

もっと汎用的に、特定の指定した引数を受け取るために全てのコマンドラインの引数を調べる必要はありません。それは cmdopts デコレータで行います。

@task
@cmdopts([
    ('username=', 'u', 'Username to use when logging in to the servers')
])
def deploy(options):
    pass

@cmdopts は長いオプション名、短いオプション名とヘルプテキストといった3つの要素を持つタプルのリストを受け取ります。長いオプション名の後に “=” があれば、そのオプションはパラメータを取ることになります。その他のオプションはブーリアンだと仮定されます。この方法のコマンドラインオプションセットは task の名前にマッチする名前空間の下で options に全て追加されます。上述したケースでは、ユーザが paver deploy -u my-user-name と実行したなら options.deploy.username がセットされます。コマンドラインで paver deploy.username=my-user-name deploy で実行するのも等価であることに注意してください。