diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 278908fc72..10abc0065d 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -2,7 +2,7 @@ To define a *CLI parameter* that can take a value from a predefined set of values you can use a standard Python `enum.Enum`: -{* docs_src/parameter_types/enum/tutorial001_py310.py hl[1,6:9,16:17] *} +{* docs_src/parameter_types/enum/tutorial001_py311.py hl[1,6:9,16:17] *} /// tip @@ -54,7 +54,7 @@ Error: Invalid value for '--network': 'CONV' is not one of 'simple', 'conv', 'ls You can make an `Enum` (choice) *CLI parameter* be case-insensitive with the `case_sensitive` parameter: -{* docs_src/parameter_types/enum/tutorial002_an_py310.py hl[19] *} +{* docs_src/parameter_types/enum/tutorial002_an_py311.py hl[19] *} And then the values of the `Enum` will be checked no matter if lower case, upper case, or a mix: diff --git a/docs_src/parameter_types/enum/tutorial001_py311.py b/docs_src/parameter_types/enum/tutorial001_py311.py new file mode 100644 index 0000000000..4aed7e686b --- /dev/null +++ b/docs_src/parameter_types/enum/tutorial001_py311.py @@ -0,0 +1,21 @@ +from enum import StrEnum + +import typer + + +class NeuralNetwork(StrEnum): + simple = "simple" + conv = "conv" + lstm = "lstm" + + +app = typer.Typer() + + +@app.command() +def main(network: NeuralNetwork = NeuralNetwork.simple): + print(f"Training neural network of type: {network.value}") + + +if __name__ == "__main__": + app() diff --git a/docs_src/parameter_types/enum/tutorial002_an_py311.py b/docs_src/parameter_types/enum/tutorial002_an_py311.py new file mode 100644 index 0000000000..a81c6a8460 --- /dev/null +++ b/docs_src/parameter_types/enum/tutorial002_an_py311.py @@ -0,0 +1,26 @@ +from enum import StrEnum +from typing import Annotated + +import typer + + +class NeuralNetwork(StrEnum): + simple = "simple" + conv = "conv" + lstm = "lstm" + + +app = typer.Typer() + + +@app.command() +def main( + network: Annotated[ + NeuralNetwork, typer.Option(case_sensitive=False) + ] = NeuralNetwork.simple, +): + print(f"Training neural network of type: {network.value}") + + +if __name__ == "__main__": + app() diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py index 6ec636d7ec..b3cbc03067 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py @@ -1,36 +1,49 @@ +import importlib import subprocess import sys +import pytest from typer.testing import CliRunner -from docs_src.parameter_types.enum import tutorial001_py310 as mod +from tests.utils import needs_py311 runner = CliRunner() -app = mod.app -def test_help(): - result = runner.invoke(app, ["--help"]) +@pytest.fixture( + name="mod", + params=[ + "tutorial001_py310", + pytest.param("tutorial001_py311", marks=needs_py311), + ], +) +def get_mod(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.parameter_types.enum.{request.param}") + return mod + + +def test_help(mod): + result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--network" in result.output assert "[simple|conv|lstm]" in result.output assert "default: simple" in result.output -def test_main(): - result = runner.invoke(app, ["--network", "conv"]) +def test_main(mod): + result = runner.invoke(mod.app, ["--network", "conv"]) assert result.exit_code == 0 assert "Training neural network of type: conv" in result.output -def test_main_default(): - result = runner.invoke(app) +def test_main_default(mod): + result = runner.invoke(mod.app) assert result.exit_code == 0 assert "Training neural network of type: simple" in result.output -def test_invalid_case(): - result = runner.invoke(app, ["--network", "CONV"]) +def test_invalid_case(mod): + result = runner.invoke(mod.app, ["--network", "CONV"]) assert result.exit_code != 0 assert "Invalid value for '--network'" in result.output assert "'CONV' is not one of" in result.output @@ -39,8 +52,8 @@ def test_invalid_case(): assert "lstm" in result.output -def test_invalid_other(): - result = runner.invoke(app, ["--network", "capsule"]) +def test_invalid_other(mod): + result = runner.invoke(mod.app, ["--network", "capsule"]) assert result.exit_code != 0 assert "Invalid value for '--network'" in result.output assert "'capsule' is not one of" in result.output @@ -49,7 +62,7 @@ def test_invalid_other(): assert "lstm" in result.output -def test_script(): +def test_script(mod): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], capture_output=True, diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002.py index 325196fae4..0b200438ed 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002.py @@ -6,6 +6,8 @@ import pytest from typer.testing import CliRunner +from tests.utils import needs_py311 + runner = CliRunner() @@ -14,6 +16,7 @@ params=[ pytest.param("tutorial002_py310"), pytest.param("tutorial002_an_py310"), + pytest.param("tutorial002_an_py311", marks=needs_py311), ], ) def get_mod(request: pytest.FixtureRequest) -> ModuleType: diff --git a/tests/utils.py b/tests/utils.py index c42f58f99a..57ec6743ab 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -6,6 +6,10 @@ from typer._completion_shared import _get_shell_name from typer.core import HAS_RICH +needs_py311 = pytest.mark.skipif( + sys.version_info < (3, 11), reason="requires python3.11+" +) + needs_linux = pytest.mark.skipif( not sys.platform.startswith("linux"), reason="Test requires Linux" )