Invoke(tasks.py)でタスクを管理する

Posted on 2020-01-26

Invoke(tasks.py)でタスク管理します。 毎回実行するソース整形手順やビルド手順などを纏めておきます。

簡単に言ってしまえば、Makefile の代用品です。
make より導入が簡単です。そして (特に Python 呼び出しが) 早いです。 というか Windows 版の make バイナリってメンテナンスされていなさそう...

$ pip install invoke

Makefile の替わりに tasks.py を書くのですが、中身は Python スクリプトなので正直なんでもありです。
依存関係や暗黙ルールは無いので、必要なら Python で書く必要があります。

というわけで、私は以下の tasks.py を使っています。 Invoke のマニュアルを読むと怒られそうな使い方ですが...

@invoke.task()
def config(context):
    """Setup config."""
    c = context.config
    c.curdir = os.path.dirname(__file__)
    c.dst = os.path.join(c.curdir, 'public')

@invoke.task(config)
def py_pretty(context):
    """Automatically formats Python code."""
    cmd = ['black', '--quiet', '--skip-string-normalization']
    for fname in glob.glob('*.py'):
        cmd.append(fname)
    # invoke.runよりsubprocess.runの方が早い。
    subprocess.run(cmd)

@invoke.task(config)
def browser(context):
    """View in browser."""
    import webbrowser
    c = context.config
    chrome = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
    browser = webbrowser.GenericBrowser(chrome)
    browser.open(f'file:///{c.dst}')

@invoke.task(config)
def _help(context):
    """Show this help."""
    print(f"invoke - Python task execution tool & library.")
    subprocess.run(['invoke', '-l'])

if __name__ == '__main__':
    invoke.call(_help)

タスク間順序しか記述できそうですので、依存関係を記述するには os.stat(file).st_mtime を比較するしかなさそうです。