How Typer handles shell autocompletion
masterclick-completion, but Typer now implements its own internal logic to provide improved features, bug fixes, and better support for modern shells, including modern versions of PowerShell on Windows.repository·master·Indexed 12 days ago
https://github.com/fastapi/typerA library for building command-line interfaces (CLIs) based on Python type hints. Built on top of Click, Typer provides automatic help generation, shell completion for Bash, Zsh, Fish, and PowerShell, and type safety. It allows developers to create simple CLIs using `typer.run()` or complex applications with multiple subcommands using `typer.Typer()`.
click-completion, but Typer now implements its own internal logic to provide improved features, bug fixes, and better support for modern shells, including modern versions of PowerShell on Windows.When you do not explicitly provide a name to @app.command(), Typer follows these rules for generating the CLI command name from the function name:
_) in the function name are automatically replaced with dashes (-).Example: def create_user(...) becomes the command create-user.
When using typer <PATH_OR_MODULE> run, the command determines which Typer application or function to execute based on a specific priority order. You can override this using CLI options.
CLI Options:
--app: The name of the variable containing the Typer() object.--func: The name of the variable containing a function intended for typer.run().Resolution Priority:
--app.--func.Typer app named app, cli, or main in the target file.Typer app found in the file (regardless of name).main, cli, or app in the target file.Typer distinguishes between two types of parameters passed to a CLI application:
python main.py "John Doe").-- (e.g., --size).When adding a sub-app to a main application, you can define the command name used in the CLI. There are two ways to set this, with the latter having higher precedence.
Precedence order (from lowest to highest priority):
typer.Typer(name="..."): The name string provided during Typer initialization.app.add_typer(sub_app, name="..."): The name string provided when adding the sub-app to a parent app. This always wins.When you create a typer.Typer() app, you can define a callback function. This callback always executes and is used to define CLI arguments and options that appear before a command.
When nesting Typer apps (adding a sub-Typer to a main Typer app), the sub-Typer can have its own callback. This callback handles CLI parameters specific to that sub-command group and can execute extra logic (like printing messages or initializing resources) before the actual command runs.
import typer
app = typer.Typer()
@app.callback()
def callback():
print("Running a users command")
@app.command()
def create(name: str):
print(f"Creating user: {name}")
if __name__ == "__main__":
app()When you call typer.run(your_function), Typer performs several automated steps to convert your function into a CLI application:
typer.Typer() application instance.command using your provided function.app()).Use typer.run() for simple scripts where you only have a single command and don't need extra configuration.
typer.Path is often sufficient for most use cases, Typer provides specialized file types that return a Python file-like object (the same type returned by open()) instead of a pathlib.Path object. This is particularly useful when migrating existing applications that expect file handles or when you want to interact with files using standard file methods like .read() and .write() directly.Typer is designed to be the "FastAPI of CLIs." It follows the same design patterns and usage as FastAPI, specifically:
typer.run(some_function).Typer distinguishes between how parameters are handled on the command line:
-- (e.g., --lastname). These are optional by default.In Python code, these correspond to function parameters. A parameter with a default value is an 'optional parameter', while one without a default value is 'required'.
rich to enhance the CLI help output. You can use Rich's markup capabilities to add color, styles, and formatting to your command descriptions and help text, making the CLI more visually appealing and readable.You can use typer.Option() to define and modify CLI options in a Typer application. It functions similarly to typer.Argument(), but provides additional features specifically for handling command-line options (flags, named parameters, etc.) rather than positional arguments.
import typer
def main(name: str = typer.Option(...)):
...
if __name__ == "__main__":
typer.run(main)