Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs for testing, password, version, context. Extra tests, include callback PR #68

Merged
merged 21 commits into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ba47507
:sparkles: Implement custom handling for callbacks with types
tiangolo Mar 18, 2020
3881f66
:sparkles: Implement type-based handling for completion functions
tiangolo Mar 18, 2020
4f10f86
:sparkles: Add examples for custom completion
tiangolo Mar 18, 2020
378f31d
:memo: Add docs for custom autocompletion
tiangolo Mar 18, 2020
62563a6
:white_check_mark: Add tests for autocompletion
tiangolo Mar 18, 2020
fc5c168
:sparkles: Document using the context
tiangolo Mar 18, 2020
18a26e2
:white_check_mark: Add tests for using the context
tiangolo Mar 18, 2020
05baf8f
:white_check_mark: Add tests init for context
tiangolo Mar 18, 2020
12975de
:wrench: Update Mypy config
tiangolo Mar 18, 2020
323d5f5
:white_check_mark: Add extra tests for completion
tiangolo Mar 18, 2020
a7c9421
:pencil2: Fix format, typos, and minor texts
tiangolo Mar 18, 2020
ebcc51b
:sparkles: Update docs for printing, include stdout, stderr, and stdin
tiangolo Mar 18, 2020
a7ed738
:pencil2: Add references to FastAPI, fix typos
tiangolo Mar 18, 2020
e967d3e
:pencil2: Fix typo in Typer CLI
tiangolo Mar 18, 2020
fda29e9
:memo: Update docs for version
tiangolo Mar 18, 2020
0c4058a
:memo: Update docs for callbacks
tiangolo Mar 18, 2020
f20b0c0
:memo: Update references to stdout/stderr in autocompletion
tiangolo Mar 18, 2020
ef63dae
:memo: Add docs for password in CLI option
tiangolo Mar 18, 2020
3fec603
:memo: Add docs and tests for Testing
tiangolo Mar 18, 2020
91af02f
:memo: Add new sections to docs
tiangolo Mar 18, 2020
705933b
:art: Fix formatting
tiangolo Mar 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@

---

Typer is library to build <abbr title="command line interface, programs executed from a terminal">CLI</abbr> applications that users will love using and developers will love creating. Based on Python 3.6+ type hints.

**Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'s little sibling. And it's intended to be the FastAPI of CLIs.
Typer is library for building <abbr title="command line interface, programs executed from a terminal">CLI</abbr> applications that users will **love using** and developers will **love creating**. Based on Python 3.6+ type hints.

The key features are:

Expand All @@ -36,11 +34,19 @@ The key features are:
* **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

<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>

**Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'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 <a href="https://click.palletsprojects.com/" class="external-link" target="_blank">Click</a>.
**Typer** stands on the shoulders of a giant. Its only internal dependency is <a href="https://click.palletsprojects.com/" class="external-link" target="_blank">Click</a>.

## Installation

Expand Down Expand Up @@ -219,7 +225,7 @@ Goodbye Ms. Camila. Have a good day.

### Recap

In summary, you declare **once** the types of parameters (*arguments* and *options*) as function parameters.
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.

Expand Down Expand Up @@ -258,7 +264,7 @@ But you can also install extras:
* Or any other tool, e.g. <a href="https://pypi.org/project/wasabi/" class="external-link" target="_blank"><code>wasabi</code></a>, <a href="https://github.com/erikrose/blessings" class="external-link" target="_blank"><code>blessings</code></a>.
* <a href="https://github.com/sarugaku/shellingham" class="external-link" target="_blank"><code>shellingham</code></a>: 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 a *CLI Option value* with the name of the shell to install completion, e.g. `--install-completion bash`.
* 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]`.

Expand All @@ -270,7 +276,7 @@ For example:

* <a href="https://github.com/click-contrib/click-spinner" class="external-link" target="_blank"><code>click-spinner</code></a>: to show the user that you are loading data. A Click plug-in.
* There are several other Click plug-ins at <a href="https://github.com/click-contrib" class="external-link" target="_blank">click-contrib</a> that you can explore.
* <a href="https://pypi.org/project/tabulate/" class="external-link" target="_blank"><code>tabulate</code></a>: to automatically display tabular data nicely. Independent of Click or typer.
* <a href="https://pypi.org/project/tabulate/" class="external-link" target="_blank"><code>tabulate</code></a>: to automatically display tabular data nicely. Independent of Click or Typer.
* <a href="https://github.com/tqdm/tqdm" class="external-link" target="_blank"><code>tqdm</code></a>: 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.

Expand Down
4 changes: 2 additions & 2 deletions docs/alternatives.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Hug is a library to create APIs and CLIs, it uses parameters in functions to dec
It inspired a lot of the ideas in **FastAPI** and **Typer**.

!!! check "Inspired **Typer** to"
Use function parameters to declare *CLI Arguments* and *CLI Options* as it simplifies a lot the development experience.
Use function parameters to declare *CLI arguments* and *CLI options* as it simplifies a lot the development experience.

### <a href="https://micheles.github.io/plac/" class="external-link" target="_blank">Plac</a>

Expand All @@ -50,7 +50,7 @@ Click is one of the most widely used libraries to create CLIs in Python.

It's a very powerful tool and there are many CLIs built with it. It is what powers **Typer** underneath.

It also uses functions with parameters for *CLI Arguments* and *CLI Options*, but the declaration of the specific *CLI Arguments*, *CLI Options*, types, etc, is done in decorators on top of the function. This requires some code repetition (e.g. a *CLI Option* name `--verbose` and a variable name `verbose`) and synchronization between two places related to the same information (the decorator and the parameter function).
It also uses functions with parameters for *CLI arguments* and *CLI options*, but the declaration of the specific *CLI arguments*, *CLI options*, types, etc, is done in decorators on top of the function. This requires some code repetition (e.g. a *CLI Option* name `--verbose` and a variable name `verbose`) and synchronization between two places related to the same information (the decorator and the parameter function).

It uses decorators on top of functions to modify the actual value of those functions, converting them to instances of a specific class. This is a clever trick, but code editors can't provide great support for autocompletion that way.

Expand Down
8 changes: 5 additions & 3 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
## Design based on **FastAPI**

<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>

**Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'s little sibling.

It follows the same design and ideas. If you know FastAPI, you already know **Typer**... more or less.
It follows the same design and ideas. If you know **FastAPI**, you already know **Typer**... more or less.

## Just Modern Python

Expand Down Expand Up @@ -56,15 +58,15 @@ The resulting CLI apps created with **Typer** have the nice features of many "pr
* `--install-completion`: Install completion for the current shell.
* `--show-completion`: Show completion for the current shell, to copy it or customize the installation.

If you didn't add `shellingham` those *CLI Options* take a parameter with the name of the shell to install completion for, e.g.:
If you didn't add `shellingham` those *CLI options* take a value with the name of the shell to install completion for, e.g.:

* `--install-completion bash`.
* `--show-completion powershell`.

Then you can tell the user to install completion after installing your CLI program and the rest will just work.

!!! tip
**Typer**'s completion is implemented internally, it uses ideas and components from Click and ideas from `click-completion`, but it doesn't use `click-completion` internally.
**Typer**'s completion is implemented internally, it uses ideas and components from Click and ideas from `click-completion`, but it doesn't use `click-completion` and re-implements some of the relevant parts of Click.

Then it extends those ideas with features and bug fixes. For example, **Typer** programs also support modern versions of PowerShell (e.g. in Windows 10) among all the other shells.

Expand Down
20 changes: 13 additions & 7 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@

---

Typer is library to build <abbr title="command line interface, programs executed from a terminal">CLI</abbr> applications that users will love using and developers will love creating. Based on Python 3.6+ type hints.

**Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'s little sibling. And it's intended to be the FastAPI of CLIs.
Typer is library for building <abbr title="command line interface, programs executed from a terminal">CLI</abbr> applications that users will **love using** and developers will **love creating**. Based on Python 3.6+ type hints.

The key features are:

Expand All @@ -36,11 +34,19 @@ The key features are:
* **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

<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>

**Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'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 <a href="https://click.palletsprojects.com/" class="external-link" target="_blank">Click</a>.
**Typer** stands on the shoulders of a giant. Its only internal dependency is <a href="https://click.palletsprojects.com/" class="external-link" target="_blank">Click</a>.

## Installation

Expand Down Expand Up @@ -219,7 +225,7 @@ Goodbye Ms. Camila. Have a good day.

### Recap

In summary, you declare **once** the types of parameters (*arguments* and *options*) as function parameters.
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.

Expand Down Expand Up @@ -258,7 +264,7 @@ But you can also install extras:
* Or any other tool, e.g. <a href="https://pypi.org/project/wasabi/" class="external-link" target="_blank"><code>wasabi</code></a>, <a href="https://github.com/erikrose/blessings" class="external-link" target="_blank"><code>blessings</code></a>.
* <a href="https://github.com/sarugaku/shellingham" class="external-link" target="_blank"><code>shellingham</code></a>: 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 a *CLI Option value* with the name of the shell to install completion, e.g. `--install-completion bash`.
* 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]`.

Expand All @@ -270,7 +276,7 @@ For example:

* <a href="https://github.com/click-contrib/click-spinner" class="external-link" target="_blank"><code>click-spinner</code></a>: to show the user that you are loading data. A Click plug-in.
* There are several other Click plug-ins at <a href="https://github.com/click-contrib" class="external-link" target="_blank">click-contrib</a> that you can explore.
* <a href="https://pypi.org/project/tabulate/" class="external-link" target="_blank"><code>tabulate</code></a>: to automatically display tabular data nicely. Independent of Click or typer.
* <a href="https://pypi.org/project/tabulate/" class="external-link" target="_blank"><code>tabulate</code></a>: to automatically display tabular data nicely. Independent of Click or Typer.
* <a href="https://github.com/tqdm/tqdm" class="external-link" target="_blank"><code>tqdm</code></a>: 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.

Expand Down
25 changes: 25 additions & 0 deletions docs/src/commands/context/tutorial001.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typer

app = typer.Typer()


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


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


@app.callback()
def main(ctx: typer.Context):
"""
Manage users in the awesome CLI app.
"""
typer.echo(f"About to execute command: {ctx.invoked_subcommand}")


if __name__ == "__main__":
app()
25 changes: 25 additions & 0 deletions docs/src/commands/context/tutorial002.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typer

app = typer.Typer()


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


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


@app.callback(invoke_without_command=True)
def main():
"""
Manage users in the awesome CLI app.
"""
typer.echo("Initializing database")


if __name__ == "__main__":
app()
26 changes: 26 additions & 0 deletions docs/src/commands/context/tutorial003.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import typer

app = typer.Typer()


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


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


@app.callback(invoke_without_command=True)
def main(ctx: typer.Context):
"""
Manage users in the awesome CLI app.
"""
if ctx.invoked_subcommand is None:
typer.echo("Initializing database")


if __name__ == "__main__":
app()
15 changes: 15 additions & 0 deletions docs/src/commands/context/tutorial004.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import typer

app = typer.Typer()


@app.command(
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
)
def main(ctx: typer.Context):
for extra_arg in ctx.args:
typer.echo(f"Got extra arg: {extra_arg}")


if __name__ == "__main__":
app()
9 changes: 9 additions & 0 deletions docs/src/options/autocompletion/tutorial001.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import typer


def main(name: str = typer.Option("World", help="The name to say hi to.")):
typer.echo(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
17 changes: 17 additions & 0 deletions docs/src/options/autocompletion/tutorial002.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import typer


def complete_name():
return ["Camila", "Carlos", "Sebastian"]


def main(
name: str = typer.Option(
"World", help="The name to say hi to.", autocompletion=complete_name
)
):
typer.echo(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
23 changes: 23 additions & 0 deletions docs/src/options/autocompletion/tutorial003.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import typer

valid_names = ["Camila", "Carlos", "Sebastian"]


def complete_name(incomplete: str):
completion = []
for name in valid_names:
if name.startswith(incomplete):
completion.append(name)
return completion


def main(
name: str = typer.Option(
"World", help="The name to say hi to.", autocompletion=complete_name
)
):
typer.echo(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
28 changes: 28 additions & 0 deletions docs/src/options/autocompletion/tutorial004.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import typer

valid_completion_items = [
("Camila", "The reader of books."),
("Carlos", "The writer of scripts."),
("Sebastian", "The type hints guy."),
]


def complete_name(incomplete: str):
completion = []
for name, help_text in valid_completion_items:
if name.startswith(incomplete):
completion_item = (name, help_text)
completion.append(completion_item)
return completion


def main(
name: str = typer.Option(
"World", help="The name to say hi to.", autocompletion=complete_name
)
):
typer.echo(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
25 changes: 25 additions & 0 deletions docs/src/options/autocompletion/tutorial005.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typer

valid_completion_items = [
("Camila", "The reader of books."),
("Carlos", "The writer of scripts."),
("Sebastian", "The type hints guy."),
]


def complete_name(incomplete: str):
for name, help_text in valid_completion_items:
if name.startswith(incomplete):
yield (name, help_text)


def main(
name: str = typer.Option(
"World", help="The name to say hi to.", autocompletion=complete_name
)
):
typer.echo(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
12 changes: 12 additions & 0 deletions docs/src/options/autocompletion/tutorial006.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import List

import typer


def main(name: List[str] = typer.Option(["World"], help="The name to say hi to.")):
for each_name in name:
typer.echo(f"Hello {each_name}")


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