Typerコールバック
app = typer.Typer()
を作成すると、それはコマンドのグループとして機能します。
そして、それを使って複数のコマンドを作成できます。
これらの各コマンドは、独自の *CLIパラメータ* を持つことができます。
ただし、これらの *CLIパラメータ* は各コマンドによって処理されるため、メインのCLIアプリケーション自体の *CLIパラメータ* を作成することはできません。
しかし、それには @app.callback()
を使用できます。
これは @app.command()
と非常によく似ていますが、メインのCLIアプリケーションの(コマンドの前に)*CLIパラメータ* を宣言します。
import typer
app = typer.Typer()
state = {"verbose": False}
@app.command()
def create(username: str):
if state["verbose"]:
print("About to create a user")
print(f"Creating user: {username}")
if state["verbose"]:
print("Just created a user")
@app.command()
def delete(username: str):
if state["verbose"]:
print("About to delete a user")
print(f"Deleting user: {username}")
if state["verbose"]:
print("Just deleted a user")
@app.callback()
def main(verbose: bool = False):
"""
Manage users in the awesome CLI app.
"""
if verbose:
print("Will write verbose output")
state["verbose"] = True
if __name__ == "__main__":
app()
ここでは、--verbose
*CLIオプション* を持つ callback
を作成します。
ヒント
--verbose
フラグを取得した後、グローバルな state
を変更し、他のコマンドで使用します。
同じことを達成する他の方法もありますが、この例ではこれで十分です。
また、コールバック関数にドキュメンテーション文字列を追加したので、デフォルトでそれが抽出され、ヘルプテキストとして使用されます。
確認
// Check the help
$ python main.py --help
// Notice the main help text, extracted from the callback function: "Manage users in the awesome CLI app."
Usage: main.py [OPTIONS] COMMAND [ARGS]...
Manage users in the awesome CLI app.
Options:
--verbose / --no-verbose [default: False]
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
create
delete
// Check the new top level CLI option --verbose
// Try it normally
$ python main.py create Camila
Creating user: Camila
// And now with --verbose
$ python main.py --verbose create Camila
Will write verbose output
About to create a user
Creating user: Camila
Just created a user
// Notice that --verbose belongs to the callback, it has to go before create or delete ⛔️
$ python main.py create --verbose Camila
Usage: main.py create [OPTIONS] USERNAME
Try "main.py create --help" for help.
Error: No such option: --verbose
作成時にコールバックを追加¶
typer.Typer()
アプリケーションを作成するときにコールバックを追加することもできます。
import typer
def callback():
print("Running a command")
app = typer.Typer(callback=callback)
@app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
これは @app.callback()
と同じことを実現します。
確認
$ python main.py create Camila
Running a command
Creating user: Camila
コールバックのオーバーライド¶
typer.Typer()
アプリケーションを作成するときにコールバックを追加した場合、@app.callback()
でオーバーライドできます。
import typer
def callback():
print("Running a command")
app = typer.Typer(callback=callback)
@app.callback()
def new_callback():
print("Override callback, running a command")
@app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
これで new_callback()
が使用されます。
確認
$ python main.py create Camila
// Notice that the message is the one from new_callback()
Override callback, running a command
Creating user: Camila
ドキュメントのためだけにコールバックを追加¶
ドキュメンテーション文字列にドキュメントを追加するためだけにコールバックを追加することもできます。
特に複数のテキスト行がある場合、インデントが自動的に処理されるため便利です。
import typer
app = typer.Typer()
@app.callback()
def callback():
"""
Manage users CLI app.
Use it with the create command.
A new user with the given NAME will be created.
"""
@app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
これで、コールバックは主にヘルプテキストのドキュメンテーション文字列を抽出するために使用されます。
確認
$ python main.py --help
// Notice all the help text extracted from the callback docstring
Usage: main.py [OPTIONS] COMMAND [ARGS]...
Manage users CLI app.
Use it with the create command.
A new user with the given NAME will be created.
Options:
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
create
// And it just works as normally
$ python main.py create Camila
Creating user: Camila
Clickグループ¶
Clickから移行してきた場合、この**Typer**コールバックは、Clickグループ の関数と同等です。
たとえば
import click
@click.group()
def cli():
pass
元の関数 cli
は、Typerコールバックと同等になります。
技術的な詳細
Clickを使用する場合、その cli
変数をClickの Group
オブジェクトに変換します。その後、元の関数はその変数に存在しなくなります。
**Typer** はそれを行いません。コールバック関数は変更されず、typer.Typer
アプリケーションに登録されるだけです。これは意図的なもので、**Typer** の設計の一部であり、エディターのオートコンプリートとタイプチェックを可能にするためです。