From 09d56ba971e68e22c5a752c6abe08033f6f401d2 Mon Sep 17 00:00:00 2001 From: Dan Walters Date: Thu, 8 Oct 2020 15:03:09 -0500 Subject: [PATCH 01/18] Support for typing.Literal as an alternative to Enum in Python 3.8+. --- docs/tutorial/parameter-types/enum.md | 39 +++++++++++++ docs_src/parameter_types/enum/tutorial003.py | 11 ++++ .../test_enum/test_tutorial003.py | 56 +++++++++++++++++++ typer/main.py | 7 +++ 4 files changed, 113 insertions(+) create mode 100644 docs_src/parameter_types/enum/tutorial003.py create mode 100644 tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 6af834bf54..561e889d0d 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -66,3 +66,42 @@ Training neural network of type: lstm ``` + +### Literal choices + +With Python 3.8+, you can also use `typing.Literal` to represent a set of possible predefined choices, without having to use an `Enum`: + +```Python hl_lines="13" +{!../docs_src/parameter_types/enum/tutorial003.py!} +``` + +
+ +```console +$ python main.py --help + +// Notice the predefined values [simple|conv|lstm] +Usage: main.py [OPTIONS] + +Options: + --network [simple|conv|lstm] [default: simple] + --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. + +// Try it +$ python main.py --network conv + +Training neural network of type: conv + +// Invalid value +$ python main.py --network capsule + +Usage: main.py [OPTIONS] +Try "main.py --help" for help. + +Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm) +``` + +
+ diff --git a/docs_src/parameter_types/enum/tutorial003.py b/docs_src/parameter_types/enum/tutorial003.py new file mode 100644 index 0000000000..6271eac338 --- /dev/null +++ b/docs_src/parameter_types/enum/tutorial003.py @@ -0,0 +1,11 @@ +from typing import Literal + +import typer + + +def main(network: Literal["simple", "conv", "lstm"] = "simple"): + typer.echo(f"Training neural network of type: {network}") + + +if __name__ == "__main__": + typer.run(main) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py new file mode 100644 index 0000000000..700fb469c7 --- /dev/null +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py @@ -0,0 +1,56 @@ +import subprocess +import sys + +import pytest +import typer +from typer.testing import CliRunner + +pytestmark = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8") + + +runner = CliRunner() + + +@pytest.fixture(scope="module") +def mod(): + from docs_src.parameter_types.enum import tutorial003 as mod + + return mod + + +@pytest.fixture(scope="module") +def app(mod): + app = typer.Typer() + app.command()(mod.main) + return app + + +def test_help(app): + result = runner.invoke(app, ["--help"]) + assert result.exit_code == 0 + assert "--network [simple|conv|lstm]" in result.output + + +def test_main(app): + result = runner.invoke(app, ["--network", "conv"]) + assert result.exit_code == 0 + assert "Training neural network of type: conv" in result.output + + +def test_invalid(app): + result = runner.invoke(app, ["--network", "capsule"]) + assert result.exit_code != 0 + assert ( + "Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm)" + in result.output + ) + + +def test_script(mod): + result = subprocess.run( + ["coverage", "run", mod.__file__, "--help"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf-8", + ) + assert "Usage" in result.stdout diff --git a/typer/main.py b/typer/main.py index 02d9a5d7fe..e7f48d2a0d 100644 --- a/typer/main.py +++ b/typer/main.py @@ -1,4 +1,6 @@ import inspect +import sys +import typing from datetime import datetime from enum import Enum from functools import update_wrapper @@ -584,6 +586,11 @@ def get_click_type( [item.value for item in annotation], case_sensitive=parameter_info.case_sensitive, ) + elif sys.version_info >= (3, 8) and typing.get_origin(annotation) == typing.Literal: + return click.Choice( + tuple(typing.get_args(annotation)), + case_sensitive=parameter_info.case_sensitive, + ) raise RuntimeError(f"Type not yet supported: {annotation}") # pragma no cover From d83f7925edb3e4e78f149d775d50363857af5177 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Jul 2022 16:58:47 +0000 Subject: [PATCH 02/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tutorial/parameter-types/enum.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 561e889d0d..61c08aee89 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -104,4 +104,3 @@ Error: Invalid value for '--network': invalid choice: capsule. (choose from simp ``` - From 095e064e1d280d2f5701dbbd42dd42d7f7c1af97 Mon Sep 17 00:00:00 2001 From: Zachary Blackwood Date: Thu, 14 Jul 2022 13:39:26 -0400 Subject: [PATCH 03/18] Correct test to handle space in output --- .../test_parameter_types/test_enum/test_tutorial003.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py index 700fb469c7..0c24ae3fe7 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py @@ -28,7 +28,7 @@ def app(mod): def test_help(app): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 - assert "--network [simple|conv|lstm]" in result.output + assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") def test_main(app): @@ -41,9 +41,13 @@ def test_invalid(app): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 assert ( - "Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm)" + "Invalid value for '--network': invalid choice: capsule. (choose from" in result.output + or "Invalid value for '--network': 'capsule' is not one of" in result.output ) + assert "simple" in result.output + assert "conv" in result.output + assert "lstm" in result.output def test_script(mod): From 847e634202a307e5d055c7c8e010c25dda35c594 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 14:31:36 +0200 Subject: [PATCH 04/18] Rename to tutorial004 to avoid conflict with master branch --- .../parameter_types/enum/{tutorial003.py => tutorial004.py} | 0 .../test_enum/{test_tutorial003.py => test_tutorial004.py} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename docs_src/parameter_types/enum/{tutorial003.py => tutorial004.py} (100%) rename tests/test_tutorial/test_parameter_types/test_enum/{test_tutorial003.py => test_tutorial004.py} (95%) diff --git a/docs_src/parameter_types/enum/tutorial003.py b/docs_src/parameter_types/enum/tutorial004.py similarity index 100% rename from docs_src/parameter_types/enum/tutorial003.py rename to docs_src/parameter_types/enum/tutorial004.py diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py similarity index 95% rename from tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py rename to tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index 0c24ae3fe7..a51487aafd 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -13,7 +13,7 @@ @pytest.fixture(scope="module") def mod(): - from docs_src.parameter_types.enum import tutorial003 as mod + from docs_src.parameter_types.enum import tutorial004 as mod return mod From f8f381abfe0e45704c60679e029a47a0409cc349 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 14:46:25 +0200 Subject: [PATCH 05/18] Add version with Annotated --- docs/tutorial/parameter-types/enum.md | 17 +++++- docs_src/parameter_types/enum/tutorial004.py | 6 +- .../parameter_types/enum/tutorial004_an.py | 14 +++++ .../test_enum/test_tutorial004_an.py | 60 +++++++++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 docs_src/parameter_types/enum/tutorial004_an.py create mode 100644 tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 61c08aee89..4e1493ff10 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -71,9 +71,20 @@ Training neural network of type: lstm With Python 3.8+, you can also use `typing.Literal` to represent a set of possible predefined choices, without having to use an `Enum`: -```Python hl_lines="13" -{!../docs_src/parameter_types/enum/tutorial003.py!} -``` +=== "Python 3.7+" + + ```Python hl_lines="13" + {!> ../docs_src/parameter_types/enum/tutorial004_an.py!} + ``` + +=== "Python 3.7+ non-Annotated" + + !!! tip + Prefer to use the `Annotated` version if possible. + + ```Python hl_lines="13" + {!> ../docs_src/parameter_types/enum/tutorial004.py!} + ```
diff --git a/docs_src/parameter_types/enum/tutorial004.py b/docs_src/parameter_types/enum/tutorial004.py index 6271eac338..642fff194d 100644 --- a/docs_src/parameter_types/enum/tutorial004.py +++ b/docs_src/parameter_types/enum/tutorial004.py @@ -3,8 +3,10 @@ import typer -def main(network: Literal["simple", "conv", "lstm"] = "simple"): - typer.echo(f"Training neural network of type: {network}") +def main( + network: Literal["simple", "conv", "lstm"] = typer.Option("simple") +): + print(f"Training neural network of type: {network}") if __name__ == "__main__": diff --git a/docs_src/parameter_types/enum/tutorial004_an.py b/docs_src/parameter_types/enum/tutorial004_an.py new file mode 100644 index 0000000000..f0383e5f7f --- /dev/null +++ b/docs_src/parameter_types/enum/tutorial004_an.py @@ -0,0 +1,14 @@ +from typing import Literal + +import typer +from typing_extensions import Annotated + + +def main( + network: Annotated[Literal["simple", "conv", "lstm"], typer.Option()] = "simple", +): + print(f"Training neural network of type: {network.value}") + + +if __name__ == "__main__": + typer.run(main) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py new file mode 100644 index 0000000000..c145da9892 --- /dev/null +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -0,0 +1,60 @@ +import subprocess +import sys + +import pytest +import typer +from typer.testing import CliRunner + +pytestmark = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8") + + +runner = CliRunner() + + +@pytest.fixture(scope="module") +def mod(): + from docs_src.parameter_types.enum import tutorial004_an as mod + + return mod + + +@pytest.fixture(scope="module") +def app(mod): + app = typer.Typer() + app.command()(mod.main) + return app + + +def test_help(app): + result = runner.invoke(app, ["--help"]) + assert result.exit_code == 0 + assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") + + +def test_main(app): + result = runner.invoke(app, ["--network", "conv"]) + assert result.exit_code == 0 + assert "Training neural network of type: conv" in result.output + + +def test_invalid(app): + result = runner.invoke(app, ["--network", "capsule"]) + assert result.exit_code != 0 + assert ( + "Invalid value for '--network': invalid choice: capsule. (choose from" + in result.output + or "Invalid value for '--network': 'capsule' is not one of" in result.output + ) + assert "simple" in result.output + assert "conv" in result.output + assert "lstm" in result.output + + +def test_script(mod): + result = subprocess.run( + ["coverage", "run", mod.__file__, "--help"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf-8", + ) + assert "Usage" in result.stdout From 89b87fe0129195393f88c3c0e116247f9629f0c1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:49:33 +0000 Subject: [PATCH 06/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs_src/parameter_types/enum/tutorial004.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs_src/parameter_types/enum/tutorial004.py b/docs_src/parameter_types/enum/tutorial004.py index 642fff194d..30b1b0eb10 100644 --- a/docs_src/parameter_types/enum/tutorial004.py +++ b/docs_src/parameter_types/enum/tutorial004.py @@ -3,9 +3,7 @@ import typer -def main( - network: Literal["simple", "conv", "lstm"] = typer.Option("simple") -): +def main(network: Literal["simple", "conv", "lstm"] = typer.Option("simple")): print(f"Training neural network of type: {network}") From d4cd3c361162b251e8e913af6015ea20701f9c5d Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 14:51:22 +0200 Subject: [PATCH 07/18] Fix --- docs_src/parameter_types/enum/tutorial004_an.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs_src/parameter_types/enum/tutorial004_an.py b/docs_src/parameter_types/enum/tutorial004_an.py index f0383e5f7f..8b7700200b 100644 --- a/docs_src/parameter_types/enum/tutorial004_an.py +++ b/docs_src/parameter_types/enum/tutorial004_an.py @@ -7,7 +7,7 @@ def main( network: Annotated[Literal["simple", "conv", "lstm"], typer.Option()] = "simple", ): - print(f"Training neural network of type: {network.value}") + print(f"Training neural network of type: {network}") if __name__ == "__main__": From 1f4b6ddc2cdb4240c07234aa48ebe8fd3e0ab18c Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 15:03:18 +0200 Subject: [PATCH 08/18] @needs_py38 fixture --- .../test_parameter_types/test_enum/test_tutorial004.py | 10 ++++++---- .../test_enum/test_tutorial004_an.py | 10 ++++++---- tests/utils.py | 4 ++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index a51487aafd..869a6cc3c1 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -1,13 +1,11 @@ import subprocess -import sys import pytest + import typer +from tests.utils import needs_py38 from typer.testing import CliRunner -pytestmark = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8") - - runner = CliRunner() @@ -25,18 +23,21 @@ def app(mod): return app +@needs_py38 def test_help(app): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") +@needs_py38 def test_main(app): result = runner.invoke(app, ["--network", "conv"]) assert result.exit_code == 0 assert "Training neural network of type: conv" in result.output +@needs_py38 def test_invalid(app): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 @@ -50,6 +51,7 @@ def test_invalid(app): assert "lstm" in result.output +@needs_py38 def test_script(mod): result = subprocess.run( ["coverage", "run", mod.__file__, "--help"], diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index c145da9892..2db72d5e76 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -1,13 +1,11 @@ import subprocess -import sys import pytest + import typer +from tests.utils import needs_py38 from typer.testing import CliRunner -pytestmark = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8") - - runner = CliRunner() @@ -25,18 +23,21 @@ def app(mod): return app +@needs_py38 def test_help(app): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") +@needs_py38 def test_main(app): result = runner.invoke(app, ["--network", "conv"]) assert result.exit_code == 0 assert "Training neural network of type: conv" in result.output +@needs_py38 def test_invalid(app): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 @@ -50,6 +51,7 @@ def test_invalid(app): assert "lstm" in result.output +@needs_py38 def test_script(mod): result = subprocess.run( ["coverage", "run", mod.__file__, "--help"], diff --git a/tests/utils.py b/tests/utils.py index 9b503ff799..d9f2a02a10 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,6 +2,10 @@ import pytest + +needs_py38 = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8+") + + needs_py310 = pytest.mark.skipif( sys.version_info < (3, 10), reason="requires python3.10+" ) From c7dd35373cba92eb9eb975cffe5eea647b69a1bd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:03:26 +0000 Subject: [PATCH 09/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_parameter_types/test_enum/test_tutorial004.py | 4 ++-- .../test_parameter_types/test_enum/test_tutorial004_an.py | 4 ++-- tests/utils.py | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index 869a6cc3c1..0c549835bf 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -1,11 +1,11 @@ import subprocess import pytest - import typer -from tests.utils import needs_py38 from typer.testing import CliRunner +from tests.utils import needs_py38 + runner = CliRunner() diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index 2db72d5e76..06cda74365 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -1,11 +1,11 @@ import subprocess import pytest - import typer -from tests.utils import needs_py38 from typer.testing import CliRunner +from tests.utils import needs_py38 + runner = CliRunner() diff --git a/tests/utils.py b/tests/utils.py index d9f2a02a10..adcf0fca95 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,7 +2,6 @@ import pytest - needs_py38 = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8+") From 9fe6ad83bec4efd3fbc750121845b1fa9e8aa634 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 15:08:19 +0200 Subject: [PATCH 10/18] further updates --- .../test_enum/test_tutorial004.py | 32 +++++++------------ .../test_enum/test_tutorial004_an.py | 32 +++++++------------ 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index 0c549835bf..ce4aade5f1 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -1,44 +1,35 @@ import subprocess +import sys -import pytest import typer from typer.testing import CliRunner from tests.utils import needs_py38 -runner = CliRunner() - - -@pytest.fixture(scope="module") -def mod(): - from docs_src.parameter_types.enum import tutorial004 as mod - - return mod +from docs_src.parameter_types.enum import tutorial004 as mod +runner = CliRunner() -@pytest.fixture(scope="module") -def app(mod): - app = typer.Typer() - app.command()(mod.main) - return app +app = typer.Typer() +app.command()(mod.main) @needs_py38 -def test_help(app): +def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") @needs_py38 -def test_main(app): +def test_main(): result = runner.invoke(app, ["--network", "conv"]) assert result.exit_code == 0 assert "Training neural network of type: conv" in result.output @needs_py38 -def test_invalid(app): +def test_invalid(): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 assert ( @@ -52,11 +43,10 @@ def test_invalid(app): @needs_py38 -def test_script(mod): +def test_script(): result = subprocess.run( - ["coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index 06cda74365..f3b275bad6 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -1,44 +1,35 @@ import subprocess +import sys -import pytest import typer from typer.testing import CliRunner +from docs_src.parameter_types.enum import tutorial004_an as mod + from tests.utils import needs_py38 runner = CliRunner() - -@pytest.fixture(scope="module") -def mod(): - from docs_src.parameter_types.enum import tutorial004_an as mod - - return mod - - -@pytest.fixture(scope="module") -def app(mod): - app = typer.Typer() - app.command()(mod.main) - return app +app = typer.Typer() +app.command()(mod.main) @needs_py38 -def test_help(app): +def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") @needs_py38 -def test_main(app): +def test_main(): result = runner.invoke(app, ["--network", "conv"]) assert result.exit_code == 0 assert "Training neural network of type: conv" in result.output @needs_py38 -def test_invalid(app): +def test_invalid(): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 assert ( @@ -52,11 +43,10 @@ def test_invalid(app): @needs_py38 -def test_script(mod): +def test_script(): result = subprocess.run( - ["coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout From bee8230ba243d7e43134a2d67bc96299d2c04db0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:08:49 +0000 Subject: [PATCH 11/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_parameter_types/test_enum/test_tutorial004.py | 3 +-- .../test_parameter_types/test_enum/test_tutorial004_an.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index ce4aade5f1..9301ba5803 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -4,9 +4,8 @@ import typer from typer.testing import CliRunner -from tests.utils import needs_py38 - from docs_src.parameter_types.enum import tutorial004 as mod +from tests.utils import needs_py38 runner = CliRunner() diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index f3b275bad6..9318c2604a 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -5,7 +5,6 @@ from typer.testing import CliRunner from docs_src.parameter_types.enum import tutorial004_an as mod - from tests.utils import needs_py38 runner = CliRunner() From 288318b7fb75d99a306ea4763c4ecd2beab30755 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 15:21:22 +0200 Subject: [PATCH 12/18] use _typing module --- docs_src/parameter_types/enum/tutorial004.py | 3 +-- docs_src/parameter_types/enum/tutorial004_an.py | 4 ++-- typer/main.py | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs_src/parameter_types/enum/tutorial004.py b/docs_src/parameter_types/enum/tutorial004.py index 30b1b0eb10..2c00659efa 100644 --- a/docs_src/parameter_types/enum/tutorial004.py +++ b/docs_src/parameter_types/enum/tutorial004.py @@ -1,6 +1,5 @@ -from typing import Literal - import typer +from typer._typing import Literal def main(network: Literal["simple", "conv", "lstm"] = typer.Option("simple")): diff --git a/docs_src/parameter_types/enum/tutorial004_an.py b/docs_src/parameter_types/enum/tutorial004_an.py index 8b7700200b..161f7c2354 100644 --- a/docs_src/parameter_types/enum/tutorial004_an.py +++ b/docs_src/parameter_types/enum/tutorial004_an.py @@ -1,7 +1,7 @@ -from typing import Literal +from typing_extensions import Annotated import typer -from typing_extensions import Annotated +from typer._typing import Literal def main( diff --git a/typer/main.py b/typer/main.py index 69f30f20d9..d6941ae633 100644 --- a/typer/main.py +++ b/typer/main.py @@ -14,6 +14,7 @@ import click +from ._typing import is_literal_type, literal_values from .completion import get_completion_inspect_parameters from .core import MarkupMode, TyperArgument, TyperCommand, TyperGroup, TyperOption from .models import ( @@ -786,9 +787,9 @@ def get_click_type( [item.value for item in annotation], case_sensitive=parameter_info.case_sensitive, ) - elif sys.version_info >= (3, 8) and typing.get_origin(annotation) == typing.Literal: + elif is_literal_type(annotation): return click.Choice( - tuple(typing.get_args(annotation)), + literal_values(annotation), case_sensitive=parameter_info.case_sensitive, ) raise RuntimeError(f"Type not yet supported: {annotation}") # pragma: no cover From 2d62d1969b9cb3b1ac400c21aa44de19c76ade03 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:22:18 +0000 Subject: [PATCH 13/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs_src/parameter_types/enum/tutorial004_an.py | 3 +-- typer/main.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/docs_src/parameter_types/enum/tutorial004_an.py b/docs_src/parameter_types/enum/tutorial004_an.py index 161f7c2354..bd68756bcf 100644 --- a/docs_src/parameter_types/enum/tutorial004_an.py +++ b/docs_src/parameter_types/enum/tutorial004_an.py @@ -1,7 +1,6 @@ -from typing_extensions import Annotated - import typer from typer._typing import Literal +from typing_extensions import Annotated def main( diff --git a/typer/main.py b/typer/main.py index d6941ae633..1013bbca6e 100644 --- a/typer/main.py +++ b/typer/main.py @@ -2,7 +2,6 @@ import os import sys import traceback -import typing from datetime import datetime from enum import Enum from functools import update_wrapper From 01d80133ffe067204bda30e097287eef2141640c Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 15:55:34 +0200 Subject: [PATCH 14/18] import Literal from typing_extensions --- docs_src/parameter_types/enum/tutorial004.py | 2 +- docs_src/parameter_types/enum/tutorial004_an.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs_src/parameter_types/enum/tutorial004.py b/docs_src/parameter_types/enum/tutorial004.py index 2c00659efa..631dc315d9 100644 --- a/docs_src/parameter_types/enum/tutorial004.py +++ b/docs_src/parameter_types/enum/tutorial004.py @@ -1,5 +1,5 @@ import typer -from typer._typing import Literal +from typing_extensions import Literal def main(network: Literal["simple", "conv", "lstm"] = typer.Option("simple")): diff --git a/docs_src/parameter_types/enum/tutorial004_an.py b/docs_src/parameter_types/enum/tutorial004_an.py index bd68756bcf..e466c0bcc3 100644 --- a/docs_src/parameter_types/enum/tutorial004_an.py +++ b/docs_src/parameter_types/enum/tutorial004_an.py @@ -1,6 +1,5 @@ import typer -from typer._typing import Literal -from typing_extensions import Annotated +from typing_extensions import Annotated, Literal def main( From 60653290960d68121747e480bfe7d5d8d040549f Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 16:06:07 +0200 Subject: [PATCH 15/18] fix highlighted lines for documentation --- docs/tutorial/parameter-types/enum.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index c410a69cae..112f027fe2 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -142,7 +142,7 @@ With Python 3.8+, you can also use `typing.Literal` to represent a set of possib === "Python 3.7+" - ```Python hl_lines="13" + ```Python hl_lines="6" {!> ../docs_src/parameter_types/enum/tutorial004_an.py!} ``` @@ -151,7 +151,7 @@ With Python 3.8+, you can also use `typing.Literal` to represent a set of possib !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="13" + ```Python hl_lines="5" {!> ../docs_src/parameter_types/enum/tutorial004.py!} ``` From 3b9034bef7d0870448667dd4c7b3d97931419f6f Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 3 Jun 2024 16:08:32 +0200 Subject: [PATCH 16/18] update console output --- docs/tutorial/parameter-types/enum.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 112f027fe2..75329f6b12 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -165,8 +165,6 @@ Usage: main.py [OPTIONS] Options: --network [simple|conv|lstm] [default: simple] - --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. // Try it @@ -180,7 +178,7 @@ $ python main.py --network capsule Usage: main.py [OPTIONS] Try "main.py --help" for help. -Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm) +Error: Invalid value for '--network': 'capsule' is not one of 'simple', 'conv', 'lstm'. ```
From 2bacd290765ef3514daa6e2bdad70deb9c9e956e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 10 Jun 2024 14:35:59 +0200 Subject: [PATCH 17/18] fix import statement to be relative --- .../test_parameter_types/test_enum/test_tutorial004.py | 2 +- .../test_parameter_types/test_enum/test_tutorial004_an.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index 9301ba5803..ccaeeb93e2 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -5,7 +5,7 @@ from typer.testing import CliRunner from docs_src.parameter_types.enum import tutorial004 as mod -from tests.utils import needs_py38 +from ....utils import needs_py38 runner = CliRunner() diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index 9318c2604a..e8bbc0a066 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -5,7 +5,7 @@ from typer.testing import CliRunner from docs_src.parameter_types.enum import tutorial004_an as mod -from tests.utils import needs_py38 +from ....utils import needs_py38 runner = CliRunner() From a7711899d6db6309bae11b6fbb4553350c8f3db4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 12:36:38 +0000 Subject: [PATCH 18/18] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_parameter_types/test_enum/test_tutorial004.py | 1 + .../test_parameter_types/test_enum/test_tutorial004_an.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index ccaeeb93e2..27714e6ebf 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -5,6 +5,7 @@ from typer.testing import CliRunner from docs_src.parameter_types.enum import tutorial004 as mod + from ....utils import needs_py38 runner = CliRunner() diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py index e8bbc0a066..e5f2f97314 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004_an.py @@ -5,6 +5,7 @@ from typer.testing import CliRunner from docs_src.parameter_types.enum import tutorial004_an as mod + from ....utils import needs_py38 runner = CliRunner()