Typer, build great CLIs. Easy to code. Based on Python type hints.

Overview

Typer

Typer, build great CLIs. Easy to code. Based on Python type hints.

Test Publish Coverage Package version


Documentation: https://typer.tiangolo.com

Source Code: https://github.com/tiangolo/typer


Typer is a library for building CLI applications that users will love using and developers will love creating. Based on Python 3.6+ type hints.

The key features are:

  • Intuitive to write: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.
  • Easy to use: It's easy to use for the final users. Automatic help, and automatic completion for all shells.
  • Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
  • Start simple: The simplest example adds only 2 lines of code to your app: 1 import, 1 function call.
  • Grow large: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments.

FastAPI of CLIs

Typer is FastAPI's little sibling.

And it's intended to be the FastAPI of CLIs.

Requirements

Python 3.6+

Typer stands on the shoulders of a giant. Its only internal dependency is Click.

Installation

$ pip install typer
---> 100%
Successfully installed typer

Example

The absolute minimum

  • Create a file main.py with:
import typer


def main(name: str):
    typer.echo(f"Hello {name}")


if __name__ == "__main__":
    typer.run(main)

Run it

Run your application:

// Run your application
$ python main.py

// You get a nice error, you are missing NAME
Usage: main.py [OPTIONS] NAME
Try "main.py --help" for help.

Error: Missing argument 'NAME'.

// You get a --help for free
$ python main.py --help

Usage: main.py [OPTIONS] NAME

Arguments:
  NAME  [required]

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.

// When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion

// Now pass the NAME argument
$ python main.py Camila

Hello Camila

// It works! 🎉

Note: auto-completion works when you create a Python package and run it with --install-completion or when you use Typer CLI.

Example upgrade

This was the simplest example possible.

Now let's see one a bit more complex.

An example with two subcommands

Modify the file main.py.

Create a typer.Typer() app, and create two subcommands with their parameters.

import typer

app = typer.Typer()


@app.command()
def hello(name: str):
    typer.echo(f"Hello {name}")


@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        typer.echo(f"Goodbye Ms. {name}. Have a good day.")
    else:
        typer.echo(f"Bye {name}!")


if __name__ == "__main__":
    app()

And that will:

  • Explicitly create a typer.Typer app.
    • The previous typer.run actually creates one implicitly for you.
  • Add two subcommands with @app.command().
  • Execute the app() itself, as if it was a function (instead of typer.run).

Run the upgraded example

// Check the --help
$ python main.py --help

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

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:
  goodbye
  hello

// You have 2 subcommands (the 2 functions): goodbye and hello

// Now get the --help for hello

$ python main.py hello --help

Usage: main.py hello [OPTIONS] NAME

Arguments:
  NAME  [required]

Options:
  --help  Show this message and exit.

// And now get the --help for goodbye

$ python main.py goodbye --help

Usage: main.py goodbye [OPTIONS] NAME

Arguments:
  NAME  [required]

Options:
  --formal / --no-formal  [default: False]
  --help                  Show this message and exit.

// Automatic --formal and --no-formal for the bool option 🎉

// And if you use it with the hello command

$ python main.py hello Camila

Hello Camila

// And with the goodbye command

$ python main.py goodbye Camila

Bye Camila!

// And with --formal

$ python main.py goodbye --formal Camila

Goodbye Ms. Camila. Have a good day.

Recap

In summary, you declare once the types of parameters (CLI arguments and CLI options) as function parameters.

You do that with standard modern Python types.

You don't have to learn a new syntax, the methods or classes of a specific library, etc.

Just standard Python 3.6+.

For example, for an int:

total: int

or for a bool flag:

force: bool

And similarly for files, paths, enums (choices), etc. And there are tools to create groups of subcommands, add metadata, extra validation, etc.

You get: great editor support, including completion and type checks everywhere.

Your users get: automatic --help, auto-completion in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using Typer CLI.

For a more complete example including more features, see the Tutorial - User Guide.

Optional Dependencies

Typer uses Click internally. That's the only dependency.

But you can also install extras:

  • colorama: and Click will automatically use it to make sure your terminal's colors always work correctly, even in Windows.
    • Then you can use any tool you want to output your terminal's colors in all the systems, including the integrated typer.style() and typer.secho() (provided by Click).
    • Or any other tool, e.g. wasabi, blessings.
  • shellingham: and Typer will automatically detect the current shell when installing completion.
    • With shellingham you can just use --install-completion.
    • Without shellingham, you have to pass the name of the shell to install completion for, e.g. --install-completion bash.

You can install typer with colorama and shellingham with pip install typer[all].

Other tools and plug-ins

Click has many plug-ins available that you can use. And there are many tools that help with command line applications that you can use as well, even if they are not related to Typer or Click.

For example:

  • click-spinner: to show the user that you are loading data. A Click plug-in.
    • There are several other Click plug-ins at click-contrib that you can explore.
  • tabulate: to automatically display tabular data nicely. Independent of Click or Typer.
  • tqdm: a fast, extensible progress bar, alternative to Typer's own typer.progressbar().
  • etc... you can re-use many of the great available tools for building CLIs.

License

This project is licensed under the terms of the MIT license.

Issues
  • [QUESTION] Dependency Injection

    [QUESTION] Dependency Injection

    First check

    • [X] I used the GitHub search to find a similar issue and didn't find it.
    • [X] I searched the Typer documentation, with the integrated search.
    • [X] I already searched in Google "How to X in Typer" and didn't find any information.
    • [X] I already searched in Google "How to X in Click" and didn't find any information.

    First of all, thank you for your amazing tools, it helps my team and I to build great products !

    Description

    How can I inject a Database connection to a "cli function" ?

    I was looking for a mecanism like Depends in FastAPI (https://fastapi.tiangolo.com/tutorial/dependencies/)

    Additional context

    I'm trying to create a cli which read files and insert them to a database but one of my subcommands is depending of a Database connection.

    For the moment I've used:

    save_app = typer.Typer()
    
    
    def get_db():
        typer.echo("Initializing database")
        db = VerticaDB(
            host=conf.get_vertica_host(),
            port=conf.get_vertica_port(),
            user=conf.get_vertica_user(),
            password=conf.get_vertica_password(),
            database=conf.get_vertica_database()
        )
        return db
    
    
    @save_app.command("save")
    def ingest_snitch_file(
            path_to_log_file: Path = typer.Option(
                ...,
                exists=True,
                readable=True,
                envvar='PATH_TO_SNITCH_FILE'
            ),
            db=typer.Option(
                hidden=True,
                default=get_db()
            )
    ):
        """
        Ingest snitch files to Database
        """
        snitch = Snitch(
            db=db,
            path_to_snitch=path_to_log_file,
            table_schema=conf.get_vertica_table_schema(),
            table_name=conf.get_vertica_table_name()
        )
        snitch.insert_log_to_database()
    
    question 
    opened by Leletir 16
  • running typer cli command from python code

    running typer cli command from python code

    How can i trigger/run typer cli specific command from python code. I guess i need to emulate command line arguments some where but not sure. Can you please help on this?

    Cli: python main.py goodbye --formal Camila

    From Code: i want to run specific command based on my need. how do i pass command line arguments, some thing like: typer_app( "goodbye --formal Camila" )

    question answered 
    opened by blnprasad 14
  • Add click 8.1.0 support

    Add click 8.1.0 support

    Some deprecated code was removed in https://github.com/pallets/click/pull/2130 resulting in the failed import of get_terminal_size from click. Per the recommendation in Click's release notes, we can import from shutil instead.

    get_terminal_size can probably be dropped from Typer's interface in the future since it's been dropped from Click's, but I'll leave that decision to a future PR. This change is backwards compatible.

    See https://click.palletsprojects.com/en/8.1.x/changes/#version-8-1-0 Closes https://github.com/tiangolo/typer/issues/377

    opened by madkinsz 12
  • [QUESTION] How to use Typer within Objects

    [QUESTION] How to use Typer within Objects

    Hello,

    I already used Typer for a few short CLIs but now I'd like to use it for a bigger, object-oriented project. I thought I find a way to use it correctly, but I'm getting errors related to the "self" argument.

    My code looks like this:

    main_menu.py

    class MainMenu:
        typer_app = typer.Typer()
        typer_app.add_typer(TournamentMenu.typer_app, name="tournament")
    
        def __init__(self):
            self.typer_app()
            self.tournament_handler = None
            self.print_menu()
            self.user_selection()
    
        def print_menu(self):
            number = typer.style("1. ", bold=True)
            typer.echo(number + "Tournois")
    
            number = typer.style("2. ", bold=True)
            typer.echo(number + "Gérer les joueurs")
    
        def user_selection(self):
            selection = typer.prompt("Entrez votre sélection: ")
            typer.echo("\n")
    
            if selection == "1":
                self.open_tournament_menu()
            else:
                self.user_selection()
    
        def open_tournament_menu(self):
            TournamentMenu()
    

    tournament_menu.py

    class TournamentMenu:
        typer_app = typer.Typer()
    
        def __init__(self):
            self.typer_app()
            self.print_menu()
            self.user_selection()
    
        def print_menu(self):
            number = typer.style("1. ", bold=True)
            typer.echo(number + "Commencer un nouveau tournoi")
    
            number = typer.style("2. ", bold=True)
            typer.echo(number + "Charger un tournoi")
    
        def user_selection(self):
            selection = typer.prompt("Entrez votre sélection: ")
    
            if selection == "1":
                self.create_new_tournament()
            else:
                self.user_selection()
    
        @typer_app.command("new")
        def create_new_tournament(self=None):
            NewTournamentMenu()
    

    new_tournament_menu.py

    class NewTournamentMenu:
        typer_app = typer.Typer()
    
        @typer_app.command()
        def __init__(self):
            self.typer_app()
            self.print_menu()
            self.user_selection()
    
        def print_menu(self):
            number = typer.style("1. ", bold=True)
            typer.echo(number + "Commencer un nouveau tournoi")
    
            number = typer.style("2. ", bold=True)
            typer.echo(number + "Charger un tournoi")
    
        def user_selection(self):
            selection = typer.prompt("Entrez votre sélection: ")
    
            if selection == "1":
                pass
            else:
                self.user_selection()
    

    But for example with python main.py tournament newI'm getting:

    Usage: dev.py [OPTIONS] SELF
    Try 'dev.py --help' for help.
    
    Error: Got unexpected extra argument (new)
    

    So, is it possible to use typer in this kind of object oriented situation ? What am I missing ?

    question 
    opened by PabloLec 12
  • [QUESTION] How to add short option

    [QUESTION] How to add short option "-h" to "--help" callback

    First check

    • [x] I used the GitHub search to find a similar issue and didn't find it.
    • [x] I searched the Typer documentation, with the integrated search.
    • [x] I already searched in Google "How to X in Typer" and didn't find any information.
    • [x] I already searched in Google "How to X in Click" and didn't find any information.

    Description

    How can I add a short option "-h" to the existing "--help" callback?

    question 
    opened by JeromeK13 10
  • [FEATURE] Add easy --version

    [FEATURE] Add easy --version

    Is your feature request related to a problem

    I'd like a way to do the standard my-command --version to exit an print the version number of the application. Click offers a version_option decorator that you can put on the entrypoint of your application to achieve this relatively easily.

    The solution you would like

    The ability to pass in a version string to an application and have the option added automatically. I'd then end up doing something like this:

    from importlib.metadata import version
    
    app = typer.Typer(version=version(__package__))
    

    Though if it's possible to attempt to extract the package version automatically without having to pass it in, that would be even better.

    Describe alternatives you've considered

    I attempted to just add a version option in my callback like below, but I can't seem to call this without passing in a command.

    @app.callback()
    def cli(display_version: bool = typer.Option(False, "--version")) -> None:
        if display_version:
            print(f"Version: {version(__package__)}")
            raise typer.Exit()
    

    However if I just try my-command --version it gives me an error saying I need to pass a command. It would be nice to be able to add custom top level options like --help which are allowed to run. Then users could implement things like --version themselves.

    enhancement 
    opened by dbanty 10
  • [QUESTION] using python-rich with Typer

    [QUESTION] using python-rich with Typer

    First check

    • [x] I used the GitHub search to find a similar issue and didn't find it.
    • [x] I searched the Typer documentation, with the integrated search.
    • [x] I already searched in Google "How to X in Typer" and didn't find any information.
    • [x] I already searched in Google "How to X in Click" and didn't find any information.

    Description

    How can I use python-rich with Typer ?

    Eg.

    from rich.console import Console
    
    console = Console()
    
    @app.command()
    def version() -> None:
        """Show project Version."""
        # typer.secho(f"project Version: {__version__}", fg=typer.colors.BRIGHT_GREEN)
    
        console.print(f"project Version: {__version__}", style="bold green")
    

    output:

    project Version: 0.0.1
    

    the problem that am facing is in test mode

    runner = CliRunner()
    
    def test_version_succeeds() -> None:
        """It exits with a status code of zero."""
        result = runner.invoke(app)
        assert result.exit_code == 0
        assert "project" in result.stdout
    

    output:

    FAILED tests/test_manage.py::test_version_succeeds - AssertionError: assert 'project' in ''
    

    So is there a way to make them work together ?

    question 
    opened by Mohamed-Kaizen 9
  • [FEATURE] Adding Typer to custom package using entry points

    [FEATURE] Adding Typer to custom package using entry points

    Wuhuu finally started using Typer and very excited about it.

    I went ahead and used the most simple example

    import typer
    
    def main(name: str):
        typer.echo(f"Hello {name}")
    
    
    if __name__ == "__main__":
        typer.run(main)
    

    which works just fine obviously. But I'd like to expose my custom package with CLI using Typer so I made a setup.py with

    from setuptools import setup
    
    setup(
        name="my_package",
        entry_points={
            "console_scripts": ["hello = my_package.cli:main"],
        },
    )
    

    Then I can call the command using hello in a terminal BUT it doesn't carry over any positional arguments. Maybe you could add some about entry points integration in the docs?

    enhancement 
    opened by mr-bjerre 9
  • [BUG] TypeError is raised if argument is capitalized

    [BUG] TypeError is raised if argument is capitalized

    Describe the bug

    If the "entry" function (the one decorated with typer.Typer.command or the one passed to typer.run) expects a capitalized argument, a TypeError will be raised (TypeError: () got an unexpected keyword argument '')

    To Reproduce

    • Create a file main.py with:
    import typer
    
    app = typer.Typer()
    
    @app.command()
    def hello(nAme: str):
        typer.echo(f"Hello {nAme}")
    
    
    if __name__ == "__main__":
        app()
    
    • Call it with:
    python main.py GodSaveTheDoge
    
    • It outputs:
    Traceback (most recent call last):
      File "githubExample.py", line 11, in <module>
        app()
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/typer/main.py", line 214, in __call__
        return get_command(self)(*args, **kwargs)
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/click/core.py", line 829, in __call__
        return self.main(*args, **kwargs)
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/click/core.py", line 782, in main
        rv = self.invoke(ctx)
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/click/core.py", line 610, in invoke
        return callback(*args, **kwargs)
      File "/data/data/com.termux/files/usr/lib/python3.8/site-packages/typer/main.py", line 497, in wrapper
        return callback(**use_params)  # type: ignore
    TypeError: hello() got an unexpected keyword argument 'name'
    
    • But I expected it to output:
    Hello GodSaveTheDoge
    

    Expected behavior

    I expected the function to be called with the capitalized version instead.

    Environment

    • OS: Android
    • Typer Version: 0.3.2
    • Python version: 3.8.0
    bug 
    opened by GodSaveTheDoge 8
  • [QUESTION] mypy complaining about missing attributes when importing typer

    [QUESTION] mypy complaining about missing attributes when importing typer

    First check

    • [x] I used the GitHub search to find a similar issue and didn't find it.
    • [x] I searched the Typer documentation, with the integrated search.
    • [x] I already searched in Google "How to X in Typer" and didn't find any information.
    • [x] I already searched in Google "How to X in Click" and didn't find any information.

    Description

    I am trying to use the type types get parsed in mypy. From my experience with mypy, the packages are either supported "out of the box" or not at all and must be ignored.

    It's a different issue than https://github.com/tiangolo/typer/issues/53

    I am not sure if I am doing something wrong or this is a bug.

    I am using mypy==0.770 on Python 3.7

    Thanks,

    Jean-Martin

    Additional context

    mypy command:

    mypy --show-error-codes --strict some_script.py
    

    mypy error (the line number will not match truncate script below)

    some_script.py:10: error: Module has no attribute "Typer"  [attr-defined]
    some_script.py:13: error: Untyped decorator makes function "main" untyped  [misc]
    some_script.py:14: error: Function is missing a return type annotation  [no-untyped-def]
    some_script.py:18: error: Module has no attribute "Option"  [attr-defined]
    some_script.py:19: error: Module has no attribute "Option"  [attr-defined]
    some_script.py:20: error: Module has no attribute "Option"  [attr-defined]
    some_script.py:21: error: Module has no attribute "Option"  [attr-defined]
    some_script.py:31: error: Module has no attribute "run"  [attr-defined]
    

    mypy config

    [mypy]
    namespace_packages = true
    
    # The following 3rd party dependencies don't have type hints. We ignore them one by one instead of
    # blindly running with --ignore-missing-imports.
    
    [mypy-typer]
    
    [mypy-setuptools]
    ignore_missing_imports = True
    

    Truncated code:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    import json
    
    import typer
    import yaml
    
    app = typer.Typer()
    
    
    @app.command(
        help="Something."
    )
    def main(
        option_a: str = typer.Option(...),
        option_b: str = typer.Option(...),
        option_c: str = typer.Option(...),
        option_d: str = typer.Option(...),
    ) -> None:
        # Non problematic code
        ...
    
    
    if __name__ == "__main__":
        typer.run(main)
    

    Workaround

    https://github.com/tiangolo/typer/issues/112#issuecomment-648347626

    question answered 
    opened by j-martin 8
  • [FEATURE] Handling Mutliple Variable Length Arguments

    [FEATURE] Handling Mutliple Variable Length Arguments

    I'm not familiar with the internals of typer and whether this is feasible, but it would be nice if it were possible to implement a command like the following:

    from typing import Optional, List
    
    import typer
    
    app = typer.Typer()
    
    
    @app.command()
    def main(first_list: List[str], option: bool = False, second_list: List[str] = ()):
        print(first_list, second_list)
    

    Where the expected behavior is:

    $ python main.py a b c --option d e f
    ('a', 'b', 'c') ('d', 'e', 'f')
    $ python main.py a b c d e f --option
    ('a', 'b', 'c', 'd', 'e', 'f') ()
    $ python main.py a b c d e f
    ('a', 'b', 'c', 'd', 'e', 'f') ()
    

    However the actual behavior in this case does not adhere to the above:

    $ python main.py a b c --option d e f
    ('a', 'b', 'c', 'd', 'e', 'f') True ()
    

    This can presently be achieved in argparse quite concisely:

    import argparse
    
    def main():
        cli = argparse.ArgumentParser()
        cli.add_argument(
            "first_list", nargs="*", type=str,
        )
        cli.add_argument(
            "--option", nargs="*", type=str, default=[],
        )
        args = cli.parse_args()
        print(args.first_list, args.option)
    
    enhancement answered 
    opened by rmorshea 8
  • Consistently use sys.executable to run subprocesses

    Consistently use sys.executable to run subprocesses

    In some scenarios, like running pytest outside of an active virtualenv, it could happen that "coverage" would refer to a different Python interpreter than the one running the tests. Admittedly that does not happen in standard development scenarios where you use a virtualenv. But it easily happens when packaging for Linux distributions that support multiple versions of Python and it can also happen when running pytest from a virtualenv without activating it. The latter is something that's convenient when testing versus multiple Python versions without using tox.

    Explicitly invoking coverage as a module on sys.executable ensures that the same binary, not process, that's also running the tests is used. This was in fact already done in some tests but not consistently across all of them.

    opened by theMarix 2
  • Ensure the PYTHONPATH is set properly when testing the tutorial scripts

    Ensure the PYTHONPATH is set properly when testing the tutorial scripts

    When packaging Typer for openSUSE I ran into errors because the tutorial scripts were unable to import their colocated modules. Curiously this only seems to be occurring when these scripts are run via coverage, as they are in the tests. Them being run via coverage however also prevents just changing the working directory for the script runs, as then the coverage file would end up in the wrong directory.

    Curiously, I have not been able to reproduce this issue on openSUSE Leap but only seen it on openSUSE Tumbleweed. Thus, there might be something weird with the Python stack or the coverage version on Tumbleweed. However, as the same PYTHONPATH-patching is also done for the tests of the tutorial code that run it directly and not as a subprocess, I think it is just consistent to also do this for the script test. Thus, please view this PR as a suggestion that improves consistency. If you think it does not provide value outside of my very specific use-case, I am completely fine with it being declined.

    For reference, this is the error that I am observing in the packaging environment and that gets resolved by this commit:

    [ 123s] =================================== FAILURES =================================== [ 123s] _________________________________ test_scripts _________________________________ [ 123s] [ 123s] mod = <module 'docs_src.subcommands.tutorial001.main' from '/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial001/main.py'> [ 123s] [ 123s] def test_scripts(mod): [ 123s] from docs_src.subcommands.tutorial001 import items, users [ 123s] [ 123s] for module in [mod, items, users]: [ 123s] result = subprocess.run( [ 123s] ["coverage", "run", module.file, "--help"], [ 123s] stdout=subprocess.PIPE, [ 123s] stderr=subprocess.PIPE, [ 123s] encoding="utf-8", [ 123s] ) [ 123s] > assert "Usage" in result.stdout [ 123s] E assert 'Usage' in '' [ 123s] E + where '' = CompletedProcess(args=['coverage', 'run', '/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial001/main.py', '--help'], returncode=1, stdout='', stderr='Traceback (most recent call last):\n File "/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial001/main.py", line 3, in \n import items\nModuleNotFoundError: No module named 'items'\n').stdout [ 123s] [ 123s] tests/test_tutorial/test_subcommands/test_tutorial001.py:94: AssertionError [ 123s] _________________________________ test_scripts _________________________________ [ 123s] [ 123s] mod = <module 'docs_src.subcommands.tutorial003.main' from '/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial003/main.py'> [ 123s] [ 123s] def test_scripts(mod): [ 123s] from docs_src.subcommands.tutorial003 import items, lands, reigns, towns, users [ 123s] [ 123s] for module in [mod, items, lands, reigns, towns, users]: [ 123s] result = subprocess.run( [ 123s] ["coverage", "run", module.file, "--help"], [ 123s] stdout=subprocess.PIPE, [ 123s] stderr=subprocess.PIPE, [ 123s] encoding="utf-8", [ 123s] ) [ 123s] > assert "Usage" in result.stdout [ 123s] E assert 'Usage' in '' [ 123s] E + where '' = CompletedProcess(args=['coverage', 'run', '/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial003/main.py', '--help'], returncode=1, stdout='', stderr='Traceback (most recent call last):\n File "/home/abuild/rpmbuild/BUILD/typer-0.4.1/docs_src/subcommands/tutorial003/main.py", line 3, in \n import items\nModuleNotFoundError: No module named 'items'\n').stdout [ 123s] [ 123s] tests/test_tutorial/test_subcommands/test_tutorial003.py:146: AssertionError

    opened by theMarix 0
  • Is there a way to override the options of a command?

    Is there a way to override the options of a command?

    First Check

    • [X] I added a very descriptive title to this issue.
    • [X] I used the GitHub search to find a similar issue and didn't find it.
    • [X] I searched the Typer documentation, with the integrated search.
    • [X] I already searched in Google "How to X in Typer" and didn't find any information.
    • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
    • [X] I already checked if it is not related to Typer but to Click.

    Commit to Help

    • [X] I commit to help with one of those options 👆

    Example Code

    import typer
    
    app = typer.Typer()
    
    @app.command()
    def hi(name: str):
       print("hi ", name)
    
    # I want to do something like this
    app.get_command("hi").options["name"] = typer.Option(..., hidden=True)
    
    # Basically, I want to dynamically manipulate the options of a specific command. Is something like this achievable?
    

    Description

    I have a use case, where I want to override the typer command options. Basically, after decorating a function as typer.command() I want to manipulate the options of this certain command later. Is this possible? I included a minimal example of what I want to do.

    Operating System

    Linux

    Operating System Details

    ubuntu 20.04

    Typer Version

    0.4.1

    Python Version

    3.8

    Additional Context

    No response

    question 
    opened by nidhaloff 0
  • Need feature to share options or arguments between commands

    Need feature to share options or arguments between commands

    First Check

    • [X] I added a very descriptive title to this issue.
    • [X] I used the GitHub search to find a similar issue and didn't find it.
    • [X] I searched the Typer documentation, with the integrated search.
    • [X] I already searched in Google "How to X in Typer" and didn't find any information.
    • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
    • [X] I already checked if it is not related to Typer but to Click.

    Commit to Help

    • [X] I commit to help with one of those options 👆

    Example Code

    from typing import Optional, List
    
    import typer
    import os
    
    app = typer.Typer()
    
    @app.command()
    def start(
      debug: bool = typer.Option(False),
      output_dir: str = typer.Option(os.getcwd()),
      flows: Optional[List[str]] = typer.Option(None, "--flow", "-f")):
      typer.echo(f"Debug mode: {debug}")
      typer.echo(f"Output Dir: {output_dir}")
      typer.echo(f"start flows: {flows}")
    
    
    @app.command()
    def stop(
      debug: bool = typer.Option(False),
      output_dir: str = typer.Option(os.getcwd())):
      typer.echo(f"Debug mode: {debug}")
      typer.echo(f"Output Dir: {output_dir}")
      typer.echo("STOP!")
    
    @app.command()
    def clean(
      debug: bool = typer.Option(False),
      output_dir: str = typer.Option(os.getcwd())):
      typer.echo(f"Debug mode: {debug}")
      typer.echo(f"Output Dir: {output_dir}")
      typer.echo("STOP!")
    
    
    if __name__ == "__main__":
        app()
    

    Description

    How can we easily add common options into multiple commands like debug or output_directory?

    Related question - https://github.com/tiangolo/typer/issues/153 - But this is not working as expected. Help section don't show message properly as commented here.

    Operating System

    Linux, Windows, macOS

    Operating System Details

    No response

    Typer Version

    ALL

    Python Version

    ALL

    Additional Context

    No response

    question 
    opened by allinhtml 0
  • Is there a way to show option related to a sub-commands using --help

    Is there a way to show option related to a sub-commands using --help

    First Check

    • [X] I added a very descriptive title to this issue.
    • [X] I used the GitHub search to find a similar issue and didn't find it.
    • [X] I searched the Typer documentation, with the integrated search.
    • [X] I already searched in Google "How to X in Typer" and didn't find any information.
    • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
    • [X] I already checked if it is not related to Typer but to Click.

    Commit to Help

    • [X] I commit to help with one of those options 👆

    Example Code

    # main file
    import typer
    
    import commands
    
    app = typer.Typer()
    
    app.add_typer(typer_instance=commands.make_structure.app, name="create", help="Create the project structure")
    app.add_typer(typer_instance=commands.lang_choise.app, name="lang", help="Pick C or Cpp language")
    
    # TODO: add a callback to the CLI indicate what's going on!!!
    
    
    if __name__== "__main__":
        app()
    
    # command 1
    import typer
    from utils.utils import create_main
    from enums.prog_lang import ProgLang
    
    
    app = typer.Typer()
    
    
    @app.command("lang")
    def language_choise(lang: ProgLang = ProgLang.c.value):
        # set the directory to work with
        
        if lang.value == "C":
            # TODO: create the main file in /src directory and write to it
            lang_code = 0
            if create_main(lang_code) != 0:
                print("exit code 2")
                return 2
            # TODO: Write in the makefile
            pass
        else:
            # TODO: create the main file in /src directory and write to it
            lang_code = 1
            if (create_main(lang_code) != 0):
                print("exit code 2")
                return 2
            # TODO: write in the makefile
            pass
    # command 2
    from typing import Optional
    import typer
    import os
    from utils.utils import build_hiarchy
    
    app = typer.Typer()
    
    # TODO: write the docs for every componenent in the app
    @app.command("create")
    def make_struct(name: str = typer.Option(...,"--name", "-n"), verbose: bool=typer.Option(False, "--verbose", "-v")) -> int:
        dir = os.getcwd()
        subdirs_to_create = ["src", "bin", "obj"]
        file_to_create = "Makefile"
        project_directory = os.path.join(dir,name)
        # build hiarchy
        if build_hiarchy(project_directory, subdirs_to_create, file_to_create, verbose) == 0:
            return 0
        typer.echo("exit code 1")
        return 1
    

    Description

    I created a small CLI scripts for building development environment for C projects. I divided my projects to main file situated in the main workspace directory and a package called command where I development most of the sub-commands. Using the API typer.add_typer(), I included the sub-commands in the main file. The issue is when I run the program : python3 main.py [sub-command] --help it doesn't show the option available for the that sub-command help

    Operating System

    Linux

    Operating System Details

    No response

    Typer Version

    0.3.2

    Python Version

    3.9.8

    Additional Context

    No response

    question 
    opened by Aziz-repo 0
Releases(0.4.1)
Owner
Sebastián Ramírez
Creator of FastAPI and Typer. Dev at @explosion. APIs, Deep Learning/ML, full-stack distributed systems, SQL/NoSQL, Python, Docker, JS, TypeScript, etc
Sebastián Ramírez
A CLI tool to build beautiful command-line interfaces with type validation.

Piou A CLI tool to build beautiful command-line interfaces with type validation. It is as simple as from piou import Cli, Option cli = Cli(descriptio

Julien Brayere 301 May 30, 2022
CalcuPy 📚 Create console-based calculators in a few lines of code.

CalcuPy ?? Create console-based calculators in a few lines of code. ?? Installation pip install calcupy ?? Usage from calcupy import Calculator calc

Dylan Tintenfich 7 Dec 1, 2021
Command line animations based on the state of the system

shell-emotions Command line animations based on the state of the system for Linux or Windows 10 The ascii animations were created using a modified ver

Simon Malave 62 Dec 12, 2021
Corgy allows you to create a command line interface in Python, without worrying about boilerplate code

corgy Elegant command line parsing for Python. Corgy allows you to create a command line interface in Python, without worrying about boilerplate code.

Jayanth Koushik 6 Feb 15, 2022
A simple terminal Christmas tree made with Python

Python Christmas Tree A simple CLI Christmas tree made with Python Installation Just clone the repository and run $ python terminal_tree.py More opti

Francisco B. 59 Dec 28, 2021
Python composable command line interface toolkit

$ click_ Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. It's the "Comm

The Pallets Projects 12.6k Jun 25, 2022
Library for building powerful interactive command line applications in Python

Python Prompt Toolkit prompt_toolkit is a library for building powerful interactive command line applications in Python. Read the documentation on rea

prompt-toolkit 7.8k Jul 2, 2022
Simple cross-platform colored terminal text in Python

Colorama Makes ANSI escape character sequences (for producing colored terminal text and cursor positioning) work under MS Windows. PyPI for releases |

Jonathan Hartley 2.9k Jun 25, 2022
Rich is a Python library for rich text and beautiful formatting in the terminal.

Rich 中文 readme • lengua española readme • Läs på svenska Rich is a Python library for rich text and beautiful formatting in the terminal. The Rich API

Will McGugan 38.2k Jun 27, 2022
emoji terminal output for Python

Emoji Emoji for Python. This project was inspired by kyokomi. Example The entire set of Emoji codes as defined by the unicode consortium is supported

Taehoon Kim 1.5k Jul 2, 2022
Python and tab completion, better together.

argcomplete - Bash tab completion for argparse Tab complete all the things! Argcomplete provides easy, extensible command line tab completion of argum

Andrey Kislyuk 1.1k Jul 2, 2022
Python library that measures the width of unicode strings rendered to a terminal

Introduction This library is mainly for CLI programs that carefully produce output for Terminals, or make pretend to be an emulator. Problem Statement

Jeff Quast 282 Jun 12, 2022
A thin, practical wrapper around terminal capabilities in Python

Blessings Coding with Blessings looks like this... from blessings import Terminal t = Terminal() print(t.bold('Hi there!')) print(t.bold_red_on_brig

Erik Rose 1.3k Jun 25, 2022
Python Command-line Application Tools

Clint: Python Command-line Interface Tools Clint is a module filled with a set of awesome tools for developing commandline applications. C ommand L in

Kenneth Reitz Archive 75 Jun 25, 2022
Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer.

Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer. The end goal is to be able to rapidly create rich termin

Will McGugan 11.8k Jul 3, 2022
Cement is an advanced Application Framework for Python, with a primary focus on CLI

Cement Framework Cement is an advanced Application Framework for Python, with a primary focus on Command Line Interfaces (CLI). Its goal is to introdu

Data Folk Labs, LLC 1.1k Jun 27, 2022
prompt_toolkit is a library for building powerful interactive command line applications in Python.

Python Prompt Toolkit prompt_toolkit is a library for building powerful interactive command line applications in Python. Read the documentation on rea

prompt-toolkit 7.8k Jun 30, 2022
Terminalcmd - a Python library which can help you to make your own terminal program with high-intellegence instruments

Terminalcmd - a Python library which can help you to make your own terminal program with high-intellegence instruments, that will make your code clear and readable.

Dallas 0 Jun 19, 2022
Async ODM (Object Document Mapper) for MongoDB based on python type hints

ODMantic Documentation: https://art049.github.io/odmantic/ Asynchronous ODM(Object Document Mapper) for MongoDB based on standard python type hints. I

Arthur Pastel 583 Jun 30, 2022
Async-first dependency injection library based on python type hints

Dependency Depression Async-first dependency injection library based on python type hints Quickstart First let's create a class we would be injecting:

Doctor 5 Jun 29, 2022
💨 Fast, Async-ready, Openapi, type hints based framework for building APIs

Fast to learn, fast to code, fast to run Django Ninja - Fast Django REST Framework Django Ninja is a web framework for building APIs with Django and P

Vitaliy Kucheryaviy 3.1k Jun 29, 2022
Data parsing and validation using Python type hints

pydantic Data validation and settings management using Python type hinting. Fast and extensible, pydantic plays nicely with your linters/IDE/brain. De

Samuel Colvin 10.3k Jul 2, 2022
Data parsing and validation using Python type hints

pydantic Data validation and settings management using Python type hinting. Fast and extensible, pydantic plays nicely with your linters/IDE/brain. De

Samuel Colvin 10.3k Jul 3, 2022
Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints.

?? Fast, Async-ready, Openapi, type hints based framework for building APIs

Vitaliy Kucheryaviy 3.1k Jul 2, 2022
Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints.

Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints. check parameters and generate API documents automatically. Flask Sugar是一个基于flask,pyddantic,类型注解的API框架, 可以检查参数并自动生成API文档

null 163 Jun 16, 2022
Force you (or your user) annotate Python function type hints.

Must-typing Force you (or your user) annotate function type hints. Notice: It's more like a joke, use it carefully. If you call must_typing in your mo

Konge 13 Feb 19, 2022
🔬 Fixed struct serialization system, using Python 3.9 annotated type hints

py-struct Fixed-size struct serialization, using Python 3.9 annotated type hints This was originally uploaded as a Gist because it's not intended as a

Alba Mendez 4 Jan 14, 2022
Type hints support for the Sphinx autodoc extension

sphinx-autodoc-typehints This extension allows you to use Python 3 annotations for documenting acceptable argument types and return value types of fun

Alex Grönholm 425 Jun 27, 2022
Pre-commit hook for upgrading type hints

This is a pre-commit hook configured to automatically upgrade your type hints to the new native types implemented in PEP 585.

snok 46 May 16, 2022