Sub-Typer Callback Override
When creating a Typer app you can define a callback function, it always executes and defines the CLI arguments and CLI options that go before a command.
When adding a Typer app inside of another, the sub-Typer can also have its own callback.
It can handle any CLI parameters that go before its own commands and execute any extra code:
import typer
app = typer.Typer()
users_app = typer.Typer()
app.add_typer(users_app, name="users")
@users_app.callback()
def users_callback():
print("Running a users command")
@users_app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
In this case it doesn't define any CLI parameters, it just writes a message.
Check it:
$ python main.py users create Camila
// Notice the first message is not created by the command function but by the callback
Running a users command
Creating user: Camila
Add a callback on creation¶
It's also possible to add a callback when creating the typer.Typer()
app that will be added to another Typer app:
import typer
app = typer.Typer()
def users_callback():
print("Running a users command")
users_app = typer.Typer(callback=users_callback)
app.add_typer(users_app, name="users")
@users_app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
This achieves exactly the same as above, it's just another place to add the callback.
Check it:
$ python main.py users create Camila
Running a users command
Creating user: Camila
Overriding the callback on creation¶
If a callback was added when creating the typer.Typer()
app, it's possible to override it with a new one using @app.callback()
.
This is the same information you saw on the section about Commands - Typer Callback, and it applies the same for sub-Typer apps:
import typer
app = typer.Typer()
def default_callback():
print("Running a users command")
users_app = typer.Typer(callback=default_callback)
app.add_typer(users_app, name="users")
@users_app.callback()
def user_callback():
print("Callback override, running users command")
@users_app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
Here we had defined a callback when creating the typer.Typer()
sub-app, but then we override it with a new callback with the function user_callback()
.
As @app.callback()
takes precedence over typer.Typer(callback=some_function)
, now our CLI app will use this new callback.
Check it:
$ python main.py users create Camila
// Notice the message from the new callback
Callback override, running users command
Creating user: Camila
Overriding the callback when adding a sub-Typer¶
Lastly, you can override the callback defined anywhere else when adding a sub-Typer with app.add_typer()
using the callback
parameter.
This has the highest priority:
import typer
app = typer.Typer()
def default_callback():
print("Running a users command")
users_app = typer.Typer(callback=default_callback)
def callback_for_add_typer():
print("I have the high land! Running users command")
app.add_typer(users_app, name="users", callback=callback_for_add_typer)
@users_app.callback()
def user_callback():
print("Callback override, running users command")
@users_app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()
Notice that the precedence goes to app.add_typer()
and is not affected by the order of execution. There's another callback defined below, but the one from app.add_typer()
wins.
Now when you use the CLI program it will use the new callback function callback_for_add_typer()
.
Check it:
$ python users create Camila
// Notice the message from the callback added in add_typer()
I have the high land! Running users command
Creating user: Camila