-
-
Notifications
You must be signed in to change notification settings - Fork 682
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Support for common pydantic types
Fixes #181
- Loading branch information
Showing
22 changed files
with
575 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
Pydantic types such as [AnyUrl](https://docs.pydantic.dev/latest/api/networks/#pydantic.networks.AnyUrl) or [EmailStr](https://docs.pydantic.dev/latest/api/networks/#pydantic.networks.EmailStr) can be very convenient to describe and validate some parameters. | ||
|
||
You can add pydantic from typer's optional dependencies | ||
|
||
<div class="termy"> | ||
|
||
```console | ||
// Pydantic comes with typer[all] | ||
$ pip install "typer[all]" | ||
---> 100% | ||
Successfully installed typer rich pydantic | ||
|
||
// Alternatively, you can install Pydantic independently | ||
$ pip install pydantic | ||
---> 100% | ||
Successfully installed pydantic | ||
``` | ||
|
||
</div> | ||
|
||
|
||
You can then use them as parameter types. | ||
|
||
=== "Python 3.6+ Argument" | ||
|
||
```Python hl_lines="5" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial001_an.py!} | ||
``` | ||
|
||
=== "Python 3.6+ Argument non-Annotated" | ||
|
||
!!! tip | ||
Prefer to use the `Annotated` version if possible. | ||
|
||
```Python hl_lines="4" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial001.py!} | ||
``` | ||
|
||
=== "Python 3.6+ Option" | ||
|
||
```Python hl_lines="5" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial002_an.py!} | ||
``` | ||
|
||
=== "Python 3.6+ Option non-Annotated" | ||
|
||
!!! tip | ||
Prefer to use the `Annotated` version if possible. | ||
|
||
```Python hl_lines="4" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial002.py!} | ||
``` | ||
|
||
These types are also supported in lists or tuples | ||
|
||
=== "Python 3.6+ list" | ||
|
||
```Python hl_lines="6" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial003_an.py!} | ||
``` | ||
|
||
=== "Python 3.6+ list non-Annotated" | ||
|
||
!!! tip | ||
Prefer to use the `Annotated` version if possible. | ||
|
||
```Python hl_lines="5" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial003.py!} | ||
``` | ||
|
||
=== "Python 3.6+ tuple" | ||
|
||
```Python hl_lines="6" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial004_an.py!} | ||
``` | ||
|
||
=== "Python 3.6+ tuple non-Annotated" | ||
|
||
!!! tip | ||
Prefer to use the `Annotated` version if possible. | ||
|
||
```Python hl_lines="5" | ||
{!> ../docs_src/parameter_types/pydantic_types/tutorial004.py!} | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import typer | ||
from pydantic import EmailStr | ||
|
||
|
||
def main(email_arg: EmailStr): | ||
typer.echo(f"email_arg: {email_arg}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import typer | ||
from pydantic import EmailStr | ||
from typing_extensions import Annotated | ||
|
||
|
||
def main(email_arg: Annotated[EmailStr, typer.Argument()]): | ||
typer.echo(f"email_arg: {email_arg}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import typer | ||
from pydantic import EmailStr | ||
|
||
|
||
def main(email_opt: EmailStr = typer.Option("[email protected]")): | ||
typer.echo(f"email_opt: {email_opt}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import typer | ||
from pydantic import EmailStr | ||
from typing_extensions import Annotated | ||
|
||
|
||
def main(email_opt: Annotated[EmailStr, typer.Option()] = "[email protected]"): | ||
typer.echo(f"email_opt: {email_opt}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from typing import List | ||
|
||
import typer | ||
from pydantic import AnyHttpUrl | ||
|
||
|
||
def main(urls: List[AnyHttpUrl] = typer.Option([], "--url")): | ||
typer.echo(f"urls: {urls}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from typing import List | ||
|
||
import typer | ||
from pydantic import AnyHttpUrl | ||
from typing_extensions import Annotated | ||
|
||
|
||
def main( | ||
urls: Annotated[List[AnyHttpUrl], typer.Option("--url", default_factory=list)], | ||
): | ||
typer.echo(f"urls: {urls}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from typing import Tuple | ||
|
||
import typer | ||
from pydantic import AnyHttpUrl, EmailStr | ||
|
||
|
||
def main( | ||
user: Tuple[str, int, EmailStr, AnyHttpUrl] = typer.Option( | ||
..., help="User name, age, email and social media URL" | ||
), | ||
): | ||
name, age, email, url = user | ||
typer.echo(f"name: {name}") | ||
typer.echo(f"age: {age}") | ||
typer.echo(f"email: {email}") | ||
typer.echo(f"url: {url}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from typing import Tuple | ||
|
||
import typer | ||
from pydantic import AnyHttpUrl, EmailStr | ||
from typing_extensions import Annotated | ||
|
||
|
||
def main( | ||
user: Annotated[ | ||
Tuple[str, int, EmailStr, AnyHttpUrl], | ||
typer.Option(help="User name, age, email and social media URL"), | ||
], | ||
): | ||
name, age, email, url = user | ||
typer.echo(f"name: {name}") | ||
typer.echo(f"age: {age}") | ||
typer.echo(f"email: {email}") | ||
typer.echo(f"url: {url}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
tests/test_tutorial/test_parameter_types/test_pydantic_types/test_tutorial001.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import subprocess | ||
import sys | ||
|
||
import typer | ||
from typer.testing import CliRunner | ||
|
||
from docs_src.parameter_types.pydantic_types import tutorial001 as mod | ||
|
||
runner = CliRunner() | ||
|
||
app = typer.Typer() | ||
app.command()(mod.main) | ||
|
||
|
||
def test_help(): | ||
result = runner.invoke(app, ["--help"]) | ||
assert result.exit_code == 0 | ||
|
||
|
||
def test_email_arg(): | ||
result = runner.invoke(app, ["[email protected]"]) | ||
assert result.exit_code == 0 | ||
assert "email_arg: [email protected]" in result.output | ||
|
||
|
||
def test_email_arg_invalid(): | ||
result = runner.invoke(app, ["invalid"]) | ||
assert result.exit_code != 0 | ||
assert "value is not a valid email address" in result.output | ||
|
||
|
||
def test_script(): | ||
result = subprocess.run( | ||
[sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], | ||
capture_output=True, | ||
encoding="utf-8", | ||
) | ||
assert "Usage" in result.stdout |
38 changes: 38 additions & 0 deletions
38
tests/test_tutorial/test_parameter_types/test_pydantic_types/test_tutorial001_an.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import subprocess | ||
import sys | ||
|
||
import typer | ||
from typer.testing import CliRunner | ||
|
||
from docs_src.parameter_types.pydantic_types import tutorial001_an as mod | ||
|
||
runner = CliRunner() | ||
|
||
app = typer.Typer() | ||
app.command()(mod.main) | ||
|
||
|
||
def test_help(): | ||
result = runner.invoke(app, ["--help"]) | ||
assert result.exit_code == 0 | ||
|
||
|
||
def test_email_arg(): | ||
result = runner.invoke(app, ["[email protected]"]) | ||
assert result.exit_code == 0 | ||
assert "email_arg: [email protected]" in result.output | ||
|
||
|
||
def test_email_arg_invalid(): | ||
result = runner.invoke(app, ["invalid"]) | ||
assert result.exit_code != 0 | ||
assert "value is not a valid email address" in result.output | ||
|
||
|
||
def test_script(): | ||
result = subprocess.run( | ||
[sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], | ||
capture_output=True, | ||
encoding="utf-8", | ||
) | ||
assert "Usage" in result.stdout |
38 changes: 38 additions & 0 deletions
38
tests/test_tutorial/test_parameter_types/test_pydantic_types/test_tutorial002.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import subprocess | ||
import sys | ||
|
||
import typer | ||
from typer.testing import CliRunner | ||
|
||
from docs_src.parameter_types.pydantic_types import tutorial002 as mod | ||
|
||
runner = CliRunner() | ||
|
||
app = typer.Typer() | ||
app.command()(mod.main) | ||
|
||
|
||
def test_help(): | ||
result = runner.invoke(app, ["--help"]) | ||
assert result.exit_code == 0 | ||
|
||
|
||
def test_email_opt(): | ||
result = runner.invoke(app, ["--email-opt", "[email protected]"]) | ||
assert result.exit_code == 0 | ||
assert "email_opt: [email protected]" in result.output | ||
|
||
|
||
def test_email_opt_invalid(): | ||
result = runner.invoke(app, ["--email-opt", "invalid"]) | ||
assert result.exit_code != 0 | ||
assert "value is not a valid email address" in result.output | ||
|
||
|
||
def test_script(): | ||
result = subprocess.run( | ||
[sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], | ||
capture_output=True, | ||
encoding="utf-8", | ||
) | ||
assert "Usage" in result.stdout |
38 changes: 38 additions & 0 deletions
38
tests/test_tutorial/test_parameter_types/test_pydantic_types/test_tutorial002_an.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import subprocess | ||
import sys | ||
|
||
import typer | ||
from typer.testing import CliRunner | ||
|
||
from docs_src.parameter_types.pydantic_types import tutorial002_an as mod | ||
|
||
runner = CliRunner() | ||
|
||
app = typer.Typer() | ||
app.command()(mod.main) | ||
|
||
|
||
def test_help(): | ||
result = runner.invoke(app, ["--help"]) | ||
assert result.exit_code == 0 | ||
|
||
|
||
def test_email_opt(): | ||
result = runner.invoke(app, ["--email-opt", "[email protected]"]) | ||
assert result.exit_code == 0 | ||
assert "email_opt: [email protected]" in result.output | ||
|
||
|
||
def test_email_opt_invalid(): | ||
result = runner.invoke(app, ["--email-opt", "invalid"]) | ||
assert result.exit_code != 0 | ||
assert "value is not a valid email address" in result.output | ||
|
||
|
||
def test_script(): | ||
result = subprocess.run( | ||
[sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], | ||
capture_output=True, | ||
encoding="utf-8", | ||
) | ||
assert "Usage" in result.stdout |
Oops, something went wrong.