typer icon indicating copy to clipboard operation
typer copied to clipboard

[FEATURE] Split commands in the same group into different files.

Open tomgrin10 opened this issue 5 years ago • 5 comments

Is your feature request related to a problem

Currently there's no way to split commands in the same group / subcommand into different files easily.

The solution you would like

I'm thinking of making it so when app.add_typer() gets no name argument it will add all commands to registered_commands, without creating a subcommand.

Example:

create.py

import typer

app = typer.Typer()


@app.command()
def create(item: str):
    typer.echo(f"Creating item: {item}")

delete.py

import typer

app = typer.Typer()


@app.command()
def delete(item: str):
    typer.echo(f"Deleting item: {item}")

main.py

import typer

import create
import delete

app = typer.Typer()
app.add_typer(create.app)
app.add_typer(delete.app)

Output:

$ python main.py --help

Usage: main.py items [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  create
  delete

Additional context

Currently giving no name to add_typer results in not adding the commands at all, even not in a subcommand.

tomgrin10 avatar Nov 09 '20 22:11 tomgrin10

I was looking to do something similar and had an idea (currently untested).

If you put the various commands into their own files as raw functions, then you can import them into your main.py. As @app.command() is just a decorator, you can can just wrap your imported functions using it.

e.g.

from .create import create
from .delete import delete

app = typer.Typer()

app.command()(create)
app.command()(delete)

lllama avatar Dec 01 '20 15:12 lllama

@lllama I currently just do this

import typer

import create
import delete

app = typer.Typer()
app.registered_commands += create.app.registered_commands + delete.app.registered_commands

I don't currently have the original code, so this may not be exactly what I wrote, but you get the idea.

tomgrin10 avatar Dec 02 '20 10:12 tomgrin10

@lllama I currently just do this

import typer

import create
import delete

app = typer.Typer()
app.registered_commands += create.app.registered_commands + delete.app.registered_commands

I don't currently have the original code, so this may not be exactly what I wrote, but you get the idea.

Thanks for this!

I am working on a little Typer app and I wanted to write my commands modularly with the style shown here, since the docs mention that Typer can recognize when a Typer app has only one command https://typer.tiangolo.com/tutorial/commands/one-or-multiple/ I was hoping to use add_typer to insert each of these But loading a 'sub-Typer' with only one command defined just adds a clunky extra layer

using a pattern like in your snippet lets me define my commands in separate files, compose them into the main application, and avoid having redundant nesting in the command hierarchy 👍🏻

I think it would be a great feature if Typer could emulate this directly when it observes that a sub-Typer has only one command. It seems strange that add_typer will silently accept being called without a 'name' argument at all

possibly related: https://github.com/tiangolo/typer/issues/119

teauxfu avatar Jun 20 '21 22:06 teauxfu

#178

Alirezaaraby avatar Sep 14 '23 12:09 Alirezaaraby

@lllama I currently just do this

import typer

import create
import delete

app = typer.Typer()
app.registered_commands += create.app.registered_commands + delete.app.registered_commands

I don't currently have the original code, so this may not be exactly what I wrote, but you get the idea.

This is same same but less typing in the "main.py" cli module than the solution given by @lllama ?

NikosAlexandris avatar Dec 13 '23 14:12 NikosAlexandris