ヨシ!

今日もご安全に!

fireでpartialな関数にhelpを表示する

概要

pythonCLIライブラリfireにてpartialな関数でも元の関数の説明が出るようにした

詳細

fireという google製のpythonCLIライブラリがある.

github.com

これが便利で,関数をマッピングするだけでサブコマンドを作成することができる. helpコマンドも関数を解析して自動で作成してくれる.

実際の--helpの表示

>poetry run zunda --help

NAME         
    zunda.cmd

SYNOPSIS
    zunda.cmd GROUP

GROUPS
    GROUP is one of the following:

     convert
       音声ファイルの変換

     preset
       現在の設定をファイルに出力する

     clear
       生成された途中ファイルをすべて削除する

     speaker
       voicevoxに内蔵されている話者一覧を表示

ただ,一括で管理しているパラメータのインスタンスをファイルで読み込んで,インスタンスとして渡したい場合に 関数をpartialでラップしてパラメータのインスタンスを渡したかった.

from functools import partial
def main():
    with argv_omit(1):
        arg = Options.from_args()
       # 引数をインスタンスに変換
        conf = OmegaConf.structured(arg)

    fire.Fire({
       # 引数全体をそれぞれの関数に渡す
        'convert': partial_doc(_convert, conf),
        'preset': partial_doc(cmd.create_preset, conf),
        'clear': partial_doc(cmd.clear_cache, arg.data_cache_dir),
        'speaker': partial_doc(cmd.show_speaker, arg.speaker_json, arg.engine_dir),
    })

その場合にfireがpartialのdocstringを表示されてしまい,本来の説明が出なくなってしまった.

説明がpartialで上書きされた

NAME
    zunda.cmd

SYNOPSIS
    zunda.cmd GROUP

GROUPS
    GROUP is one of the following:

     convert
       partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.      

     preset
       partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.      

     clear
       partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.      

     speaker
       partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.    

fireは関数の場合,__doc__からヘルプに使う説明を引っ張ってきているようなので上書きする関数を作成して修正した.

stackoverflow.com

def partial_doc(f: Callable, *args, **kwargs):
    partial_f = partial(f, *args, **kwargs)
    partial_f.__doc__ = f.__doc__
    return partial_f

変更後,以前と同じように表示されるようになった.

def main():
    with argv_omit(1):
        arg = Options.from_args()
        conf = OmegaConf.structured(arg)

    fire.Fire({
        'convert': partial_doc(_convert, conf),
        'preset': partial_doc(cmd.create_preset, conf),
        'clear': partial_doc(cmd.clear_cache, arg.data_cache_dir),
        'speaker': partial_doc(cmd.show_speaker, arg.speaker_json, arg.engine_dir),
    })
NAME
    zunda.cmd

SYNOPSIS
    zunda.cmd GROUP

GROUPS
    GROUP is one of the following:

     convert
       音声ファイルの変換

     preset
       現在の設定をファイルに出力する

     clear
       生成された途中ファイルをすべて削除する

     speaker
       voicevoxに内蔵されている話者一覧を表示