SubCommands in a Single File
In some cases, it's possible that your application code needs to live on a single file.
You can still use the same ideas:
import typer_cloup as typer
app = typer.Typer()
items_app = typer.Typer()
app.add_sub(items_app, name="items")
users_app = typer.Typer()
app.add_sub(users_app, name="users")
@items_app.command("create")
def items_create(item: str):
typer.echo(f"Creating item: {item}")
@items_app.command("delete")
def items_delete(item: str):
typer.echo(f"Deleting item: {item}")
@items_app.command("sell")
def items_sell(item: str):
typer.echo(f"Selling item: {item}")
@users_app.command("create")
def users_create(user_name: str):
typer.echo(f"Creating user: {user_name}")
@users_app.command("delete")
def users_delete(user_name: str):
typer.echo(f"Deleting user: {user_name}")
if __name__ == "__main__":
app()
There are several things to notice here...
Apps at the top¶
First, you can create typer.Typer()
objects and add them to another one at the top.
It doesn't have to be done after creating the subcommands:
import typer_cloup as typer
app = typer.Typer()
items_app = typer.Typer()
app.add_sub(items_app, name="items")
users_app = typer.Typer()
app.add_sub(users_app, name="users")
@items_app.command("create")
def items_create(item: str):
typer.echo(f"Creating item: {item}")
@items_app.command("delete")
def items_delete(item: str):
typer.echo(f"Deleting item: {item}")
@items_app.command("sell")
def items_sell(item: str):
typer.echo(f"Selling item: {item}")
@users_app.command("create")
def users_create(user_name: str):
typer.echo(f"Creating user: {user_name}")
@users_app.command("delete")
def users_delete(user_name: str):
typer.echo(f"Deleting user: {user_name}")
if __name__ == "__main__":
app()
You can add the commands (subcommands) to each typer.Typer()
app later and it will still work.
Function names¶
As you now have subcommands like create
for users
and for items
, you can no longer call the functions with just the name, like def create()
, because they would overwrite each other.
So we use longer names:
import typer_cloup as typer
app = typer.Typer()
items_app = typer.Typer()
app.add_sub(items_app, name="items")
users_app = typer.Typer()
app.add_sub(users_app, name="users")
@items_app.command("create")
def items_create(item: str):
typer.echo(f"Creating item: {item}")
@items_app.command("delete")
def items_delete(item: str):
typer.echo(f"Deleting item: {item}")
@items_app.command("sell")
def items_sell(item: str):
typer.echo(f"Selling item: {item}")
@users_app.command("create")
def users_create(user_name: str):
typer.echo(f"Creating user: {user_name}")
@users_app.command("delete")
def users_delete(user_name: str):
typer.echo(f"Deleting user: {user_name}")
if __name__ == "__main__":
app()
Command name¶
We are naming the functions with longer names so that they don't overwrite each other.
But we still want the subcommands to be create
, delete
, etc.
To call them like:
// We want this ✔️
$ python main.py items create
instead of:
// We don't want this ⛔️
$ python main.py items items-create
So we pass the name we want to use for each subcommand as the function argument to the decorator:
import typer_cloup as typer
app = typer.Typer()
items_app = typer.Typer()
app.add_sub(items_app, name="items")
users_app = typer.Typer()
app.add_sub(users_app, name="users")
@items_app.command("create")
def items_create(item: str):
typer.echo(f"Creating item: {item}")
@items_app.command("delete")
def items_delete(item: str):
typer.echo(f"Deleting item: {item}")
@items_app.command("sell")
def items_sell(item: str):
typer.echo(f"Selling item: {item}")
@users_app.command("create")
def users_create(user_name: str):
typer.echo(f"Creating user: {user_name}")
@users_app.command("delete")
def users_delete(user_name: str):
typer.echo(f"Deleting user: {user_name}")
if __name__ == "__main__":
app()
Check it¶
It still works the same:
// Check the help
$ python main.py --help
Usage: main.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
items
users
Check the items
command:
// Check the help for items
$ python main.py items --help
// It shows its own commands (subcommands): create, delete, sell
Usage: main.py items [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
create
delete
sell
// Try it
$ python main.py items create Wand
Creating item: Wand
$ python main.py items sell Vase
Selling item: Vase
And the same for the users
command:
$ python main.py users --help
Usage: main.py users [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
create
delete
// Try it
$ python main.py users create Camila
Creating user: Camila