Skip to content

Commit

Permalink
✨ Add support for PEP-593 Annotated for specifying options and argu…
Browse files Browse the repository at this point in the history
…ments (#584)

* ✨ Add support for PEP-593 `Annotated` for specifying options and arguments

Implements #184

* Revert things I did to get a 3.6 virtualenv 😅

A lot of the dev dependency packages weren't installable on 3.6, so I
had to remove them from the pyproject.toml.

This commit adds them back

* Fix mypy/lint errors

* Skip coverage on test lines that shouldn't execute

* Missed a spot

* ♻️ Tweak examples and tests with Annotated, add extra examples and tests

* 🔥 Remove Pydantic-specific logic from _typing.py

* 📝 Update docs to use new Annotated examples

* 📝 Add docs introducing Annotated and previous versions

* 🔧 Add commented out MkDocs config for highlighting docs examples

* ✅ Fix tests for Click 7

---------

Co-authored-by: Sebastián Ramírez <[email protected]>
  • Loading branch information
ryangalamb and tiangolo authored May 2, 2023
1 parent 1260b8d commit 458a492
Show file tree
Hide file tree
Showing 178 changed files with 6,728 additions and 268 deletions.
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ source =
tests
docs_src

omit =
typer/_typing.py

parallel = True
context = '${CONTEXT}'

Expand Down
39 changes: 32 additions & 7 deletions docs/tutorial/arguments/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@ That way the *CLI argument* will be optional *and also* have a default value.

We can also use `typer.Argument()` to make a *CLI argument* have a default value other than `None`:

```Python hl_lines="4"
{!../docs_src/arguments/default/tutorial001.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/default/tutorial001_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/default/tutorial001.py!}
```

!!! tip
Because now the value will be a `str` passed by the user or the default value of `"Wade Wilson"` which is also a `str`, we know the value will never be `None`, so we don't have to (and shouldn't) use `Optional[str]`.
Expand Down Expand Up @@ -49,16 +60,30 @@ Hello Camila

## Dynamic default value

And we can even make the default value be dynamically generated by passing a function as the first function argument:
And we can even make the default value be dynamically generated by passing a function as the `default_factory` argument:

```Python hl_lines="6 7 10"
{!../docs_src/arguments/default/tutorial002.py!}
```
=== "Python 3.6+"

```Python hl_lines="7-8 11"
{!> ../docs_src/arguments/default/tutorial002_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="6-7 10"
{!> ../docs_src/arguments/default/tutorial002.py!}
```

In this case, we created the function `get_name` that will just return a random `str` each time.

And we pass it as the first function argument to `typer.Argument()`.

!!! tip
The word "factory" in `default_factory` is just a fancy way of saying "function that will create the default value".

Check it:

<div class="termy">
Expand Down
51 changes: 42 additions & 9 deletions docs/tutorial/arguments/envvar.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@ You can also configure a *CLI argument* to read a value from an environment vari

To do that, use the `envvar` parameter for `typer.Argument()`:

```Python hl_lines="4"
{!../docs_src/arguments/envvar/tutorial001.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/envvar/tutorial001_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/envvar/tutorial001.py!}
```

In this case, the *CLI argument* `name` will have a default value of `"World"`, but will also read any value passed to the environment variable `AWESOME_NAME` if no value is provided in the command line:

Expand Down Expand Up @@ -51,9 +62,20 @@ Hello Mr. Czernobog

You are not restricted to a single environment variable, you can declare a list of environment variables that could be used to get a value if it was not passed in the command line:

```Python hl_lines="4"
{!../docs_src/arguments/envvar/tutorial002.py!}
```
=== "Python 3.6+"

```Python hl_lines="6"
{!> ../docs_src/arguments/envvar/tutorial002_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/envvar/tutorial002.py!}
```

Check it:

Expand Down Expand Up @@ -90,9 +112,20 @@ Hello Mr. Anubis

By default, environment variables used will be shown in the help text, but you can disable them with `show_envvar=False`:

```Python hl_lines="4"
{!../docs_src/arguments/envvar/tutorial003.py!}
```
=== "Python 3.6+"

```Python hl_lines="7"
{!> ../docs_src/arguments/envvar/tutorial003_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/envvar/tutorial003.py!}
```

Check it:

Expand Down
136 changes: 112 additions & 24 deletions docs/tutorial/arguments/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,20 @@ Now that you also know how to use `typer.Argument()`, let's use it to add docume

You can use the `help` parameter to add a help text for a *CLI argument*:

```Python hl_lines="4"
{!../docs_src/arguments/help/tutorial001.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/help/tutorial001_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/help/tutorial001.py!}
```

And it will be used in the automatic `--help` option:

Expand All @@ -41,9 +52,20 @@ Options:

And of course, you can also combine that `help` with the <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</abbr>:

```Python hl_lines="4 5 6 7"
{!../docs_src/arguments/help/tutorial002.py!}
```
=== "Python 3.6+"

```Python hl_lines="5-8"
{!> ../docs_src/arguments/help/tutorial002_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4-7"
{!> ../docs_src/arguments/help/tutorial002.py!}
```

And the `--help` option will combine all the information:

Expand Down Expand Up @@ -72,9 +94,20 @@ Options:

If you have a *CLI argument* with a default value, like `"World"`:

```Python hl_lines="4"
{!../docs_src/arguments/help/tutorial003.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/help/tutorial003_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/help/tutorial003.py!}
```

It will show that default value in the help text:

Expand All @@ -101,9 +134,20 @@ Options:

But you can disable that if you want to, with `show_default=False`:

```Python hl_lines="4"
{!../docs_src/arguments/help/tutorial004.py!}
```
=== "Python 3.6+"

```Python hl_lines="7"
{!> ../docs_src/arguments/help/tutorial004_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/help/tutorial004.py!}
```

And then it won't show the default value:

Expand Down Expand Up @@ -138,9 +182,20 @@ Options:

You can use the same `show_default` to pass a custom string (instead of a `bool`) to customize the default value to be shown in the help text:

```Python hl_lines="6"
{!../docs_src/arguments/help/tutorial005.py!}
```
=== "Python 3.6+"

```Python hl_lines="9"
{!> ../docs_src/arguments/help/tutorial005_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="6"
{!> ../docs_src/arguments/help/tutorial005.py!}
```

And it will be used in the help text:

Expand Down Expand Up @@ -187,9 +242,20 @@ But you can customize it with the `metavar` parameter for `typer.Argument()`.

For example, let's say you don't want to have the default of `NAME`, you want to have `username`, in lowercase, and you really want ✨ emojis ✨ everywhere:

```Python hl_lines="4"
{!../docs_src/arguments/help/tutorial006.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/help/tutorial006_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/help/tutorial006.py!}
```

Now the generated help text will have `✨username✨` instead of `NAME`:

Expand Down Expand Up @@ -217,9 +283,20 @@ You might want to show the help information for *CLI arguments* in different pan

If you have installed Rich as described in the docs for [Printing and Colors](../printing.md){.internal-link target=_blank}, you can set the `rich_help_panel` parameter to the name of the panel where you want this *CLI argument* to be shown:

```Python hl_lines="7 10"
{!../docs_src/arguments/help/tutorial007.py!}
```
=== "Python 3.6+"

```Python hl_lines="8 12"
{!> ../docs_src/arguments/help/tutorial007_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="7 10"
{!> ../docs_src/arguments/help/tutorial007.py!}
```

Then, if you check the `--help` option, you will see a default panel named "`Arguments`" for the *CLI arguments* that don't have a custom `rich_help_panel`.

Expand Down Expand Up @@ -267,9 +344,20 @@ If you want, you can make a *CLI argument* **not** show up in the `Arguments` se

You will probably not want to do this normally, but it's possible:

```Python hl_lines="4"
{!../docs_src/arguments/help/tutorial008.py!}
```
=== "Python 3.6+"

```Python hl_lines="5"
{!> ../docs_src/arguments/help/tutorial008_an.py!}
```

=== "Python 3.6+ non-Annotated"

!!! tip
Prefer to use the `Annotated` version if possible.

```Python hl_lines="4"
{!> ../docs_src/arguments/help/tutorial008.py!}
```

Check it:

Expand Down
Loading

0 comments on commit 458a492

Please sign in to comment.