From 5bea9cf205df92cb24526f63ac6c6dc9d2b888c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 11:41:14 -0500 Subject: [PATCH 01/37] =?UTF-8?q?=F0=9F=94=A5=20Remove=20support=20for=20C?= =?UTF-8?q?lick=207,=20require=20Click=208+=20(#760)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 11 +- docs/tutorial/options/callback-and-context.md | 18 +- docs_src/options/callback/tutorial001.py | 4 +- docs_src/options/callback/tutorial001_an.py | 4 +- docs_src/options/callback/tutorial002.py | 4 +- docs_src/options/callback/tutorial002_an.py | 4 +- docs_src/options/callback/tutorial003.py | 4 +- docs_src/options/callback/tutorial003_an.py | 4 +- docs_src/options/callback/tutorial004.py | 4 +- docs_src/options/callback/tutorial004_an.py | 4 +- pyproject.toml | 2 +- tests/test_compat/test_option_get_help.py | 3 +- .../test_completion_install.py | 6 +- tests/test_completion/test_completion_show.py | 23 ++- tests/test_others.py | 37 ++-- .../test_callback/test_tutorial001.py | 6 +- .../test_help/test_tutorial001.py | 24 +-- .../test_help/test_tutorial001_an.py | 24 +-- .../test_options/test_tutorial001.py | 30 +-- .../test_options/test_tutorial001_an.py | 30 +-- .../test_tutorial002.py | 7 +- .../test_tutorial002_an.py | 7 +- .../test_tutorial001.py | 7 +- .../test_tutorial001_an.py | 7 +- .../test_name/test_tutorial001.py | 6 +- .../test_name/test_tutorial001_an.py | 6 +- .../test_prompt/test_tutorial003.py | 7 +- .../test_prompt/test_tutorial003_an.py | 7 +- .../test_tutorial008.py | 3 +- .../test_tutorial008_an.py | 3 +- .../test_tutorial009.py | 3 +- .../test_tutorial009_an.py | 3 +- .../test_bool/test_tutorial001.py | 7 +- .../test_bool/test_tutorial001_an.py | 7 +- .../test_bool/test_tutorial002.py | 7 +- .../test_bool/test_tutorial002_an.py | 7 +- .../test_datetime/test_tutorial001.py | 6 +- .../test_enum/test_tutorial001.py | 16 +- .../test_index/test_tutorial001.py | 7 +- .../test_number/test_tutorial001.py | 20 +- .../test_number/test_tutorial001_an.py | 20 +- .../test_number/test_tutorial002.py | 4 - .../test_number/test_tutorial002_an.py | 4 - .../test_uuid/test_tutorial001.py | 4 - .../test_using_click/test_tutorial003.py | 3 +- typer/_compat_utils.py | 5 - ...etion_click8.py => _completion_classes.py} | 0 typer/_completion_click7.py | 157 ---------------- typer/_completion_shared.py | 6 +- typer/completion.py | 15 +- typer/core.py | 177 ++++++------------ typer/models.py | 6 +- typer/rich_utils.py | 24 +-- 53 files changed, 194 insertions(+), 620 deletions(-) delete mode 100644 typer/_compat_utils.py rename typer/{_completion_click8.py => _completion_classes.py} (100%) delete mode 100644 typer/_completion_click7.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5dd3c73170..533c4cf417 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,9 +13,6 @@ jobs: strategy: matrix: python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] - click-version: - - click-7 - - click-8 fail-fast: false steps: @@ -28,18 +25,14 @@ jobs: run: pip install flit - name: Install Dependencies run: python -m flit install --symlink - - name: Install Click 7 - if: matrix.click-version == 'click-7' - run: pip install "click<8.0.0" - name: Lint - if: ${{ matrix.click-version == 'click-8' }} run: bash scripts/lint.sh - run: mkdir coverage - name: Test run: bash scripts/test.sh env: - COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.click-version }} - CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.click-version }} + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} + CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - name: Store coverage files uses: actions/upload-artifact@v3 with: diff --git a/docs/tutorial/options/callback-and-context.md b/docs/tutorial/options/callback-and-context.md index c6c80114c7..4c1c3a6527 100644 --- a/docs/tutorial/options/callback-and-context.md +++ b/docs/tutorial/options/callback-and-context.md @@ -8,7 +8,7 @@ For example, you could do some validation before the rest of the code is execute === "Python 3.7+" - ```Python hl_lines="5-8 11" + ```Python hl_lines="7-10 13" {!> ../docs_src/options/callback/tutorial001_an.py!} ``` @@ -17,7 +17,7 @@ For example, you could do some validation before the rest of the code is execute !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="4-7 10" + ```Python hl_lines="6-9 12" {!> ../docs_src/options/callback/tutorial001.py!} ``` @@ -107,7 +107,7 @@ Let's say that when the callback is running, we want to show a message saying th === "Python 3.7+" - ```Python hl_lines="6" + ```Python hl_lines="8" {!> ../docs_src/options/callback/tutorial002_an.py!} ``` @@ -116,7 +116,7 @@ Let's say that when the callback is running, we want to show a message saying th !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="5" + ```Python hl_lines="7" {!> ../docs_src/options/callback/tutorial002.py!} ``` @@ -155,7 +155,7 @@ The "context" has some additional data about the current execution of your progr === "Python 3.7+" - ```Python hl_lines="5-7" + ```Python hl_lines="7-9" {!> ../docs_src/options/callback/tutorial003_an.py!} ``` @@ -164,7 +164,7 @@ The "context" has some additional data about the current execution of your progr !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="4-6" + ```Python hl_lines="6-8" {!> ../docs_src/options/callback/tutorial003.py!} ``` @@ -172,7 +172,7 @@ The `ctx.resilient_parsing` will be `True` when handling completion, so you can But it will be `False` when calling the program normally. So you can continue the execution of your previous code. -That's all is needed to fix completion 🚀 +That's all is needed to fix completion. 🚀 Check it: @@ -200,7 +200,7 @@ The same way you can access the `typer.Context` by declaring a function paramete === "Python 3.7+" - ```Python hl_lines="5 8" + ```Python hl_lines="7 10" {!> ../docs_src/options/callback/tutorial004_an.py!} ``` @@ -209,7 +209,7 @@ The same way you can access the `typer.Context` by declaring a function paramete !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="4 7" + ```Python hl_lines="6 9" {!> ../docs_src/options/callback/tutorial004.py!} ``` diff --git a/docs_src/options/callback/tutorial001.py b/docs_src/options/callback/tutorial001.py index 6af7c09fa8..f64b8b7b68 100644 --- a/docs_src/options/callback/tutorial001.py +++ b/docs_src/options/callback/tutorial001.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer @@ -7,7 +9,7 @@ def name_callback(value: str): return value -def main(name: str = typer.Option(..., callback=name_callback)): +def main(name: Optional[str] = typer.Option(default=None, callback=name_callback)): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial001_an.py b/docs_src/options/callback/tutorial001_an.py index 9f57221dc8..c539740bc8 100644 --- a/docs_src/options/callback/tutorial001_an.py +++ b/docs_src/options/callback/tutorial001_an.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer from typing_extensions import Annotated @@ -8,7 +10,7 @@ def name_callback(value: str): return value -def main(name: Annotated[str, typer.Option(callback=name_callback)]): +def main(name: Annotated[Optional[str], typer.Option(callback=name_callback)] = None): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial002.py b/docs_src/options/callback/tutorial002.py index df9f24b43e..98863c7546 100644 --- a/docs_src/options/callback/tutorial002.py +++ b/docs_src/options/callback/tutorial002.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer @@ -8,7 +10,7 @@ def name_callback(value: str): return value -def main(name: str = typer.Option(..., callback=name_callback)): +def main(name: Optional[str] = typer.Option(default=None, callback=name_callback)): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial002_an.py b/docs_src/options/callback/tutorial002_an.py index 2f5a67f8be..f9a7013d43 100644 --- a/docs_src/options/callback/tutorial002_an.py +++ b/docs_src/options/callback/tutorial002_an.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer from typing_extensions import Annotated @@ -9,7 +11,7 @@ def name_callback(value: str): return value -def main(name: Annotated[str, typer.Option(callback=name_callback)]): +def main(name: Annotated[Optional[str], typer.Option(callback=name_callback)] = None): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial003.py b/docs_src/options/callback/tutorial003.py index 1891b9793e..1cc5e9b3ed 100644 --- a/docs_src/options/callback/tutorial003.py +++ b/docs_src/options/callback/tutorial003.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer @@ -10,7 +12,7 @@ def name_callback(ctx: typer.Context, value: str): return value -def main(name: str = typer.Option(..., callback=name_callback)): +def main(name: Optional[str] = typer.Option(default=None, callback=name_callback)): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial003_an.py b/docs_src/options/callback/tutorial003_an.py index 18a374d65d..609b82268d 100644 --- a/docs_src/options/callback/tutorial003_an.py +++ b/docs_src/options/callback/tutorial003_an.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer from typing_extensions import Annotated @@ -11,7 +13,7 @@ def name_callback(ctx: typer.Context, value: str): return value -def main(name: Annotated[str, typer.Option(callback=name_callback)]): +def main(name: Annotated[Optional[str], typer.Option(callback=name_callback)] = None): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial004.py b/docs_src/options/callback/tutorial004.py index 61c9c19991..9502c65e34 100644 --- a/docs_src/options/callback/tutorial004.py +++ b/docs_src/options/callback/tutorial004.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer @@ -10,7 +12,7 @@ def name_callback(ctx: typer.Context, param: typer.CallbackParam, value: str): return value -def main(name: str = typer.Option(..., callback=name_callback)): +def main(name: Optional[str] = typer.Option(default=None, callback=name_callback)): print(f"Hello {name}") diff --git a/docs_src/options/callback/tutorial004_an.py b/docs_src/options/callback/tutorial004_an.py index d8412ed784..670f0cbc66 100644 --- a/docs_src/options/callback/tutorial004_an.py +++ b/docs_src/options/callback/tutorial004_an.py @@ -1,3 +1,5 @@ +from typing import Optional + import typer from typing_extensions import Annotated @@ -11,7 +13,7 @@ def name_callback(ctx: typer.Context, param: typer.CallbackParam, value: str): return value -def main(name: Annotated[str, typer.Option(callback=name_callback)]): +def main(name: Annotated[Optional[str], typer.Option(callback=name_callback)] = None): print(f"Hello {name}") diff --git a/pyproject.toml b/pyproject.toml index 1d96c62021..c6e282a545 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ classifiers = [ "License :: OSI Approved :: MIT License" ] requires = [ - "click >= 7.1.1, <9.0.0", + "click >= 8.0.0", "typing-extensions >= 3.7.4.3", ] description-file = "README.md" diff --git a/tests/test_compat/test_option_get_help.py b/tests/test_compat/test_option_get_help.py index 41a9d5269c..c4966dc9b6 100644 --- a/tests/test_compat/test_option_get_help.py +++ b/tests/test_compat/test_option_get_help.py @@ -52,5 +52,4 @@ def test_completion(): "_TYPER_COMPLETE_TESTING": "True", }, ) - # TODO: when deprecating Click 7, remove second option - assert "Jonny" in result.stdout or "_files" in result.stdout + assert "Jonny" in result.stdout diff --git a/tests/test_completion/test_completion_install.py b/tests/test_completion/test_completion_install.py index 0856b9b565..32c6f71dae 100644 --- a/tests/test_completion/test_completion_install.py +++ b/tests/test_completion/test_completion_install.py @@ -27,11 +27,7 @@ def test_completion_install_no_shell(): "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) - # TODO: when deprecating Click 7, remove second option - assert ( - "Option '--install-completion' requires an argument" in result.stderr - or "--install-completion option requires an argument" in result.stderr - ) + assert "Option '--install-completion' requires an argument" in result.stderr def test_completion_install_bash(): diff --git a/tests/test_completion/test_completion_show.py b/tests/test_completion/test_completion_show.py index 02e70cb8ae..196f27f048 100644 --- a/tests/test_completion/test_completion_show.py +++ b/tests/test_completion/test_completion_show.py @@ -1,9 +1,18 @@ import os import subprocess import sys +from unittest import mock + +import shellingham +import typer +from typer.testing import CliRunner from docs_src.commands.index import tutorial001 as mod +runner = CliRunner() +app = typer.Typer() +app.command()(mod.main) + def test_completion_show_no_shell(): result = subprocess.run( @@ -17,11 +26,7 @@ def test_completion_show_no_shell(): "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) - # TODO: when deprecating Click 7, remove second option - assert ( - "Option '--show-completion' requires an argument" in result.stderr - or "--show-completion option requires an argument" in result.stderr - ) + assert "Option '--show-completion' requires an argument" in result.stderr def test_completion_show_bash(): @@ -146,3 +151,11 @@ def test_completion_source_pwsh(): "Register-ArgumentCompleter -Native -CommandName tutorial001.py -ScriptBlock $scriptblock" in result.stdout ) + + +def test_completion_show_invalid_shell(): + with mock.patch.object( + shellingham, "detect_shell", return_value=("xshell", "/usr/bin/xshell") + ): + result = runner.invoke(app, ["--show-completion"]) + assert "Shell xshell not supported" in result.stdout diff --git a/tests/test_others.py b/tests/test_others.py index 2c257518ca..3bc7fd7d72 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -10,6 +10,7 @@ import shellingham import typer import typer.completion +from typer.core import _split_opt from typer.main import solve_typer_info_defaults, solve_typer_info_help from typer.models import ParameterInfo, TyperInfo from typer.testing import CliRunner @@ -155,11 +156,7 @@ def test_completion_untyped_parameters(): }, ) assert "info name is: completion_no_types.py" in result.stderr - # TODO: when deprecating Click 7, remove second option - assert ( - "args is: []" in result.stderr - or "args is: ['--name', 'Sebastian', '--name']" in result.stderr - ) + assert "args is: []" in result.stderr assert "incomplete is: Ca" in result.stderr assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout @@ -188,11 +185,7 @@ def test_completion_untyped_parameters_different_order_correct_names(): }, ) assert "info name is: completion_no_types_order.py" in result.stderr - # TODO: when deprecating Click 7, remove second option - assert ( - "args is: []" in result.stderr - or "args is: ['--name', 'Sebastian', '--name']" in result.stderr - ) + assert "args is: []" in result.stderr assert "incomplete is: Ca" in result.stderr assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout @@ -233,12 +226,8 @@ def main(arg1, arg2: int, arg3: "int", arg4: bool = False, arg5: "bool" = False) print(f"arg5: {type(arg5)} {arg5}") result = runner.invoke(app, ["Hello", "2", "invalid"]) - # TODO: when deprecating Click 7, remove second option - assert ( - "Invalid value for 'ARG3': 'invalid' is not a valid integer" in result.stdout - or "Invalid value for 'ARG3': invalid is not a valid integer" in result.stdout - ) + assert "Invalid value for 'ARG3': 'invalid' is not a valid integer" in result.stdout result = runner.invoke(app, ["Hello", "2", "3", "--arg4", "--arg5"]) assert ( "arg1: Hello\narg2: 2\narg3: 3\narg4: True\narg5: True\n" @@ -255,3 +244,21 @@ def main(name: str): result = runner.invoke(app, ["main", "-h"]) assert "Show this message and exit." in result.stdout + + +def test_split_opt(): + prefix, opt = _split_opt("--verbose") + assert prefix == "--" + assert opt == "verbose" + + prefix, opt = _split_opt("//verbose") + assert prefix == "//" + assert opt == "verbose" + + prefix, opt = _split_opt("-verbose") + assert prefix == "-" + assert opt == "verbose" + + prefix, opt = _split_opt("verbose") + assert prefix == "" + assert opt == "verbose" diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py index 8bda783bb9..68bcdf1fd0 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py @@ -63,11 +63,7 @@ def test_delete_verbose(): def test_wrong_verbose(): result = runner.invoke(app, ["delete", "--verbose", "Camila"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "No such option: --verbose" in result.output - or "no such option: --verbose" in result.output - ) + assert "No such option: --verbose" in result.output def test_script(): diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py index bad756c405..e2c99e35c4 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py @@ -69,44 +69,28 @@ def test_create(): def test_delete(): result = runner.invoke(app, ["delete", "Camila"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Deleting user: Camila" in result.output def test_no_delete(): result = runner.invoke(app, ["delete", "Camila"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all(): result = runner.invoke(app, ["delete-all"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Deleting all users" in result.output def test_no_delete_all(): result = runner.invoke(app, ["delete-all"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Operation cancelled" in result.output diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py b/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py index 8be85698d0..e349718463 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py @@ -69,44 +69,28 @@ def test_create(): def test_delete(): result = runner.invoke(app, ["delete", "Camila"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Deleting user: Camila" in result.output def test_no_delete(): result = runner.invoke(app, ["delete", "Camila"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all(): result = runner.invoke(app, ["delete-all"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Deleting all users" in result.output def test_no_delete_all(): result = runner.invoke(app, ["delete-all"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Operation cancelled" in result.output diff --git a/tests/test_tutorial/test_commands/test_options/test_tutorial001.py b/tests/test_tutorial/test_commands/test_options/test_tutorial001.py index ce3307e3f8..f15e76bb5f 100644 --- a/tests/test_tutorial/test_commands/test_options/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_options/test_tutorial001.py @@ -29,55 +29,35 @@ def test_create(): def test_delete(): result = runner.invoke(app, ["delete", "Camila"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Deleting user: Camila" in result.output def test_no_delete(): result = runner.invoke(app, ["delete", "Camila"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all(): result = runner.invoke(app, ["delete-all"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Deleting all users" in result.output def test_no_delete_all(): result = runner.invoke(app, ["delete-all"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all_force(): result = runner.invoke(app, ["delete-all", "--force"]) assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" not in result.output - or "Are you sure you want to delete ALL users? [y/N]:" not in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" not in result.output assert "Deleting all users" in result.output diff --git a/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py b/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py index b65fe03f44..9dd919c0f4 100644 --- a/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py +++ b/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py @@ -29,55 +29,35 @@ def test_create(): def test_delete(): result = runner.invoke(app, ["delete", "Camila"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Deleting user: Camila" in result.output def test_no_delete(): result = runner.invoke(app, ["delete", "Camila"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete the user? [y/n]:" in result.output - or "Are you sure you want to delete the user? [y/N]:" in result.output - ) + assert "Are you sure you want to delete the user? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all(): result = runner.invoke(app, ["delete-all"], input="y\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Deleting all users" in result.output def test_no_delete_all(): result = runner.invoke(app, ["delete-all"], input="n\n") assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" in result.output - or "Are you sure you want to delete ALL users? [y/N]:" in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" in result.output assert "Operation cancelled" in result.output def test_delete_all_force(): result = runner.invoke(app, ["delete-all", "--force"]) assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Are you sure you want to delete ALL users? [y/n]:" not in result.output - or "Are you sure you want to delete ALL users? [y/N]:" not in result.output - ) + assert "Are you sure you want to delete ALL users? [y/n]:" not in result.output assert "Deleting all users" in result.output diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py index 88e2dfe506..ad323c3681 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py @@ -30,12 +30,7 @@ def test_defaults(): def test_invalid_args(): result = runner.invoke(app, ["Draco", "Hagrid"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Argument 'names' takes 3 values" in result.stdout - or "argument names takes 3 values" in result.stdout - ) + assert "Argument 'names' takes 3 values" in result.stdout def test_valid_args(): diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py index d99a38e651..e420acb46d 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py @@ -32,12 +32,7 @@ def test_defaults(): def test_invalid_args(): result = runner.invoke(app, ["Draco", "Hagrid"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Argument 'names' takes 3 values" in result.stdout - or "argument names takes 3 values" in result.stdout - ) + assert "Argument 'names' takes 3 values" in result.stdout def test_valid_args(): diff --git a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py index fcb216595c..013b19f873 100644 --- a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py +++ b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py @@ -35,12 +35,7 @@ def test_user_2(): def test_invalid_user(): result = runner.invoke(app, ["--user", "Camila", "50"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Option '--user' requires 3 arguments" in result.output - or "--user option requires 3 arguments" in result.output - ) + assert "Option '--user' requires 3 arguments" in result.output def test_script(): diff --git a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py index c83b7b6bb2..de8cfa9f20 100644 --- a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py +++ b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py @@ -35,12 +35,7 @@ def test_user_2(): def test_invalid_user(): result = runner.invoke(app, ["--user", "Camila", "50"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Option '--user' requires 3 arguments" in result.output - or "--user option requires 3 arguments" in result.output - ) + assert "Option '--user' requires 3 arguments" in result.output def test_script(): diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial001.py b/tests/test_tutorial/test_options/test_name/test_tutorial001.py index fd0f5d59c6..da14c934c1 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial001.py @@ -29,11 +29,7 @@ def test_call(): def test_call_no_args(): result = runner.invoke(app, ["--name"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Option '--name' requires an argument" in result.output - or "--name option requires an argument" in result.output - ) + assert "Option '--name' requires an argument" in result.output def test_script(): diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py index 5bf1aa7d9c..c5c57b2ee8 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py @@ -29,11 +29,7 @@ def test_call(): def test_call_no_args(): result = runner.invoke(app, ["--name"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( - "Option '--name' requires an argument" in result.output - or "--name option requires an argument" in result.output - ) + assert "Option '--name' requires an argument" in result.output def test_script(): diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py index ba3204adab..2684bcedc9 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py @@ -23,12 +23,7 @@ def test_prompt_not_equal(): app, input="Old Project\nNew Spice\nOld Project\nOld Project\n" ) assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Error: The two entered values do not match" in result.output - or "Error: the two entered values do not match" in result.output - ) + assert "Error: The two entered values do not match" in result.output assert "Deleting project Old Project" in result.output diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py index 4588b31b06..b163386438 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py @@ -23,12 +23,7 @@ def test_prompt_not_equal(): app, input="Old Project\nNew Spice\nOld Project\nOld Project\n" ) assert result.exit_code == 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Error: The two entered values do not match" in result.output - or "Error: the two entered values do not match" in result.output - ) + assert "Error: The two entered values do not match" in result.output assert "Deleting project Old Project" in result.output diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py index 78a787a821..982c7d94c0 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py @@ -25,8 +25,7 @@ def test_completion(): assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout assert '"Sebastian":"The type hints guy."' in result.stdout - # TODO: when deprecating Click 7, remove second option - assert "[]" in result.stderr or "['--name']" in result.stderr + assert "[]" in result.stderr def test_1(): diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py index adacd66e8d..8c662543ea 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py @@ -25,8 +25,7 @@ def test_completion(): assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout assert '"Sebastian":"The type hints guy."' in result.stdout - # TODO: when deprecating Click 7, remove second option - assert "[]" in result.stderr or "['--name']" in result.stderr + assert "[]" in result.stderr def test_1(): diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py index ee7918d5dc..999240d970 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py @@ -25,8 +25,7 @@ def test_completion(): assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout assert '"Sebastian":"The type hints guy."' not in result.stdout - # TODO: when deprecating Click 7, remove second option - assert "[]" in result.stderr or "['--name', 'Sebastian', '--name']" in result.stderr + assert "[]" in result.stderr def test_1(): diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py index 8ac91a0aaa..b56523bcbb 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py @@ -25,8 +25,7 @@ def test_completion(): assert '"Camila":"The reader of books."' in result.stdout assert '"Carlos":"The writer of scripts."' in result.stdout assert '"Sebastian":"The type hints guy."' not in result.stdout - # TODO: when deprecating Click 7, remove second option - assert "[]" in result.stderr or "['--name', 'Sebastian', '--name']" in result.stderr + assert "[]" in result.stderr def test_1(): diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py index cc4b4548fe..356a99284b 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py @@ -34,12 +34,7 @@ def test_force(): def test_invalid_no_force(): result = runner.invoke(app, ["--no-force"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "No such option: --no-force" in result.output - or "no such option: --no-force" in result.output - ) + assert "No such option: --no-force" in result.output def test_script(): diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py index 52cd1cd290..ef92385022 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py @@ -34,12 +34,7 @@ def test_force(): def test_invalid_no_force(): result = runner.invoke(app, ["--no-force"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "No such option: --no-force" in result.output - or "no such option: --no-force" in result.output - ) + assert "No such option: --no-force" in result.output def test_script(): diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py index 339ebce3b6..413ccd4f67 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py @@ -53,12 +53,7 @@ def test_reject(): def test_invalid_no_accept(): result = runner.invoke(app, ["--no-accept"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "No such option: --no-accept" in result.output - or "no such option: --no-accept" in result.output - ) + assert "No such option: --no-accept" in result.output def test_script(): diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py index d13e645438..0498c3299f 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py @@ -53,12 +53,7 @@ def test_reject(): def test_invalid_no_accept(): result = runner.invoke(app, ["--no-accept"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "No such option: --no-accept" in result.output - or "no such option: --no-accept" in result.output - ) + assert "No such option: --no-accept" in result.output def test_script(): diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py index f6be63e645..215e5deb8a 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py @@ -32,11 +32,7 @@ def test_invalid(): "Invalid value for 'BIRTH:[%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S]':" in result.stdout ) - # TODO: when deprecating Click 7, remove second option - assert ( - "'july-19-1989' does not match the formats" in result.output - or "invalid datetime format: july-19-1989. (choose from" in result.output - ) + assert "'july-19-1989' does not match the formats" in result.output assert "%Y-%m-%d" in result.output assert "%Y-%m-%dT%H:%M:%S" in result.output assert "%Y-%m-%d %H:%M:%S" in result.output 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 d1debcd399..3dc997a2d2 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 @@ -29,13 +29,7 @@ def test_main(): def test_invalid_case(): result = runner.invoke(app, ["--network", "CONV"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Invalid value for '--network': 'CONV' is not one of" in result.output - or "Invalid value for '--network': invalid choice: CONV. (choose from" - in result.output - ) + assert "Invalid value for '--network': 'CONV' is not one of" in result.output assert "simple" in result.output assert "conv" in result.output assert "lstm" in result.output @@ -44,13 +38,7 @@ def test_invalid_case(): def test_invalid_other(): result = runner.invoke(app, ["--network", "capsule"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Invalid value for '--network': 'capsule' is not one of" in result.output - or "Invalid value for '--network': invalid choice: capsule. (choose from" - in result.output - ) + assert "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 diff --git a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py index 62d16a60ab..b232dba532 100644 --- a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py @@ -35,12 +35,7 @@ def test_params(): def test_invalid(): result = runner.invoke(app, ["Camila", "--age", "15.3"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Invalid value for '--age': '15.3' is not a valid integer" in result.output - or "Invalid value for '--age': 15.3 is not a valid integer" in result.output - ) + assert "Invalid value for '--age': '15.3' is not a valid integer" in result.output def test_script(): diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index 1e08f0d493..efec0467b9 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -45,39 +45,23 @@ def test_params(): def test_invalid_id(): result = runner.invoke(app, ["1002"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option assert ( - ( - "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000." - in result.output - ) - or "Invalid value for 'ID': 1002 is not in the valid range of 0 to 1000." - in result.output + "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000." in result.output ) def test_invalid_age(): result = runner.invoke(app, ["5", "--age", "15"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Invalid value for '--age': 15 is not in the range x>=18" in result.output - or "Invalid value for '--age': 15 is smaller than the minimum valid value 18." - in result.output - ) + assert "Invalid value for '--age': 15 is not in the range x>=18" in result.output def test_invalid_score(): result = runner.invoke(app, ["5", "--age", "20", "--score", "100.5"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( "Invalid value for '--score': 100.5 is not in the range x<=100." in result.output - or "Invalid value for '--score': 100.5 is bigger than the maximum valid value" - in result.output ) diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py index c77048b460..6bc60beeb2 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py @@ -45,39 +45,23 @@ def test_params(): def test_invalid_id(): result = runner.invoke(app, ["1002"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option assert ( - ( - "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000." - in result.output - ) - or "Invalid value for 'ID': 1002 is not in the valid range of 0 to 1000." - in result.output + "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000." in result.output ) def test_invalid_age(): result = runner.invoke(app, ["5", "--age", "15"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - - assert ( - "Invalid value for '--age': 15 is not in the range x>=18" in result.output - or "Invalid value for '--age': 15 is smaller than the minimum valid value 18." - in result.output - ) + assert "Invalid value for '--age': 15 is not in the range x>=18" in result.output def test_invalid_score(): result = runner.invoke(app, ["5", "--age", "20", "--score", "100.5"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( "Invalid value for '--score': 100.5 is not in the range x<=100." in result.output - or "Invalid value for '--score': 100.5 is bigger than the maximum valid value" - in result.output ) diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py index 2e33f2e7ba..2bc0e23e17 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py @@ -15,12 +15,8 @@ def test_invalid_id(): result = runner.invoke(app, ["1002"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000" in result.output - or "Invalid value for 'ID': 1002 is not in the valid range of 0 to 1000." - in result.output ) diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py index 31f9729cc9..de1eaa982f 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py @@ -15,12 +15,8 @@ def test_invalid_id(): result = runner.invoke(app, ["1002"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( "Invalid value for 'ID': 1002 is not in the range 0<=x<=1000" in result.output - or "Invalid value for 'ID': 1002 is not in the valid range of 0 to 1000." - in result.output ) diff --git a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py index b22ad1251c..0f60bc544d 100644 --- a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py @@ -22,13 +22,9 @@ def test_main(): def test_invalid_uuid(): result = runner.invoke(app, ["7479706572-72756c6573"]) assert result.exit_code != 0 - # TODO: when deprecating Click 7, remove second option - assert ( "Invalid value for 'USER_ID': '7479706572-72756c6573' is not a valid UUID" in result.output - or "Invalid value for 'USER_ID': 7479706572-72756c6573 is not a valid UUID value" - in result.output ) diff --git a/tests/test_tutorial/test_using_click/test_tutorial003.py b/tests/test_tutorial/test_using_click/test_tutorial003.py index 58af540680..55f7f16f9e 100644 --- a/tests/test_tutorial/test_using_click/test_tutorial003.py +++ b/tests/test_tutorial/test_using_click/test_tutorial003.py @@ -10,8 +10,7 @@ def test_cli(): result = runner.invoke(mod.typer_click_object, []) - # TODO: when deprecating Click 7, remove second option - assert "Missing command" in result.stdout or "Usage" in result.stdout + assert "Missing command" in result.stdout def test_help(): diff --git a/typer/_compat_utils.py b/typer/_compat_utils.py deleted file mode 100644 index 637e8ceb0d..0000000000 --- a/typer/_compat_utils.py +++ /dev/null @@ -1,5 +0,0 @@ -import click - - -def _get_click_major() -> int: - return int(click.__version__.split(".")[0]) diff --git a/typer/_completion_click8.py b/typer/_completion_classes.py similarity index 100% rename from typer/_completion_click8.py rename to typer/_completion_classes.py diff --git a/typer/_completion_click7.py b/typer/_completion_click7.py deleted file mode 100644 index 9f4ad73f30..0000000000 --- a/typer/_completion_click7.py +++ /dev/null @@ -1,157 +0,0 @@ -import os -import re -import sys - -import click -import click._bashcomplete - -from ._completion_shared import get_completion_script - -try: - import shellingham -except ImportError: # pragma: nocover - shellingham = None - - -_click_patched = False - - -def do_bash_complete(cli: click.Command, prog_name: str) -> bool: - cwords = click.parser.split_arg_string(os.getenv("COMP_WORDS", "")) - cword = int(os.getenv("COMP_CWORD", 0)) - args = cwords[1:cword] - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - for item in click._bashcomplete.get_choices(cli, prog_name, args, incomplete): - click.echo(item[0]) - return True - - -def do_zsh_complete(cli: click.Command, prog_name: str) -> bool: - completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") - cwords = click.parser.split_arg_string(completion_args) - args = cwords[1:] - if args and not completion_args.endswith(" "): - incomplete = args[-1] - args = args[:-1] - else: - incomplete = "" - - def escape(s: str) -> str: - return ( - s.replace('"', '""') - .replace("'", "''") - .replace("$", "\\$") - .replace("`", "\\`") - ) - - res = [] - for item, help in click._bashcomplete.get_choices(cli, prog_name, args, incomplete): - if help: - res.append(f'"{escape(item)}":"{escape(help)}"') - else: - res.append(f'"{escape(item)}"') - if res: - args_str = "\n".join(res) - click.echo(f"_arguments '*: :(({args_str}))'") - else: - click.echo("_files") - return True - - -def do_fish_complete(cli: click.Command, prog_name: str) -> bool: - completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") - complete_action = os.getenv("_TYPER_COMPLETE_FISH_ACTION", "") - cwords = click.parser.split_arg_string(completion_args) - args = cwords[1:] - if args and not completion_args.endswith(" "): - incomplete = args[-1] - args = args[:-1] - else: - incomplete = "" - show_args = [] - for item, help in click._bashcomplete.get_choices(cli, prog_name, args, incomplete): - if help: - formatted_help = re.sub(r"\s", " ", help) - show_args.append(f"{item}\t{formatted_help}") - else: - show_args.append(item) - if complete_action == "get-args": - if show_args: - for arg in show_args: - click.echo(arg) - elif complete_action == "is-args": - if show_args: - # Activate complete args (no files) - sys.exit(0) - else: - # Deactivate complete args (allow files) - sys.exit(1) - return True - - -def do_powershell_complete(cli: click.Command, prog_name: str) -> bool: - completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") - incomplete = os.getenv("_TYPER_COMPLETE_WORD_TO_COMPLETE", "") - cwords = click.parser.split_arg_string(completion_args) - args = cwords[1:] - for item, help in click._bashcomplete.get_choices(cli, prog_name, args, incomplete): - click.echo(f"{item}:::{help or ' '}") - - return True - - -def do_shell_complete(*, cli: click.Command, prog_name: str, shell: str) -> bool: - if shell == "bash": - return do_bash_complete(cli, prog_name) - elif shell == "zsh": - return do_zsh_complete(cli, prog_name) - elif shell == "fish": - return do_fish_complete(cli, prog_name) - elif shell in {"powershell", "pwsh"}: - return do_powershell_complete(cli, prog_name) - return False - - -def handle_shell_complete( - cli: click.Command, prog_name: str, complete_var: str, complete_instr: str -) -> bool: - if "_" not in complete_instr: - click.echo("Invalid completion instruction.", err=True) - sys.exit(1) - command, shell = complete_instr.split("_", 1) - if command == "source": - click.echo( - get_completion_script( - prog_name=prog_name, complete_var=complete_var, shell=shell - ) - ) - return True - elif command == "complete": - return do_shell_complete(cli=cli, prog_name=prog_name, shell=shell) - click.echo(f'Completion instruction "{command}" not supported.', err=True) - return False - - -def completion_init() -> None: - global _click_patched - if not _click_patched: - testing = os.getenv("_TYPER_COMPLETE_TESTING") - - def testing_handle_shell_complete( - cli: click.Command, prog_name: str, complete_var: str, complete_instr: str - ) -> bool: - result = handle_shell_complete(cli, prog_name, complete_var, complete_instr) - if result: - # Avoid fast_exit(1) in Click so Coverage can finish - sys.exit(1) - return result - - if testing: - click._bashcomplete.bashcomplete = testing_handle_shell_complete - else: - click._bashcomplete.bashcomplete = handle_shell_complete - _click_patched = True diff --git a/typer/_completion_shared.py b/typer/_completion_shared.py index 7cbaf98d75..3202e18ed8 100644 --- a/typer/_completion_shared.py +++ b/typer/_completion_shared.py @@ -1,7 +1,6 @@ import os import re import subprocess -import sys from enum import Enum from pathlib import Path from typing import Optional, Tuple @@ -14,9 +13,6 @@ shellingham = None -from typing import Optional - - class Shells(str, Enum): bash = "bash" zsh = "zsh" @@ -88,7 +84,7 @@ def get_completion_script(*, prog_name: str, complete_var: str, shell: str) -> s script = _completion_scripts.get(shell) if script is None: click.echo(f"Shell {shell} not supported.", err=True) - sys.exit(1) + raise click.exceptions.Exit(1) return ( script % dict( diff --git a/typer/completion.py b/typer/completion.py index c42ad95b81..fce42965d3 100644 --- a/typer/completion.py +++ b/typer/completion.py @@ -4,7 +4,7 @@ import click -from ._compat_utils import _get_click_major +from ._completion_classes import completion_init from ._completion_shared import Shells, get_completion_script, install from .models import ParamMeta from .params import Option @@ -102,24 +102,13 @@ def _install_completion_no_auto_placeholder_function( pass # pragma no cover -def completion_init() -> None: - if _get_click_major() < 8: - from ._completion_click7 import completion_init - - completion_init() - else: - from ._completion_click8 import completion_init - - completion_init() - - # Re-implement Click's shell_complete to add error message with: # Invalid completion instruction # To use 7.x instruction style for compatibility # And to add extra error messages, for compatibility with Typer in previous versions # This is only called in new Command method, only used by Click 8.x+ def shell_complete( - cli: click.BaseCommand, + cli: click.Command, ctx_args: MutableMapping[str, Any], prog_name: str, complete_var: str, diff --git a/typer/core.py b/typer/core.py index ec17bbcf83..c56acf8522 100644 --- a/typer/core.py +++ b/typer/core.py @@ -5,7 +5,6 @@ from enum import Enum from gettext import gettext as _ from typing import ( - TYPE_CHECKING, Any, Callable, Dict, @@ -23,11 +22,9 @@ import click.core import click.formatting import click.parser +import click.shell_completion import click.types import click.utils -from typer.completion import completion_init - -from ._compat_utils import _get_click_major if sys.version_info >= (3, 8): from typing import Literal @@ -42,28 +39,17 @@ except ImportError: # pragma: nocover rich = None # type: ignore -if TYPE_CHECKING: # pragma: no cover - if _get_click_major() == 7: - import click.shell_completion - MarkupMode = Literal["markdown", "rich", None] -# TODO: when deprecating Click 7, remove this -def _typer_param_shell_complete( - self: click.core.Parameter, ctx: click.Context, incomplete: str -) -> List["click.shell_completion.CompletionItem"]: - if self._custom_shell_complete is not None: - results = self._custom_shell_complete(ctx, self, incomplete) - - if results and isinstance(results[0], str): - from click.shell_completion import CompletionItem - - results = [CompletionItem(c) for c in results] - - return cast(List["click.shell_completion.CompletionItem"], results) - - return self.type.shell_complete(ctx, self, incomplete) +# Copy from click.parser._split_opt +def _split_opt(opt: str) -> Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] def _typer_param_setup_autocompletion_compat( @@ -125,7 +111,7 @@ def _get_default_string( ) elif isinstance(default_value, Enum): default_string = str(default_value.value) - elif callable(default_value): + elif inspect.isfunction(default_value): default_string = _("(dynamic)") elif isinstance(obj, TyperOption) and obj.is_bool_flag and obj.secondary_opts: # For boolean flags that have distinct True/False opts, @@ -136,11 +122,11 @@ def _get_default_string( # )[1] if obj.default: if obj.opts: - default_string = click.parser.split_opt(obj.opts[0])[1] + default_string = _split_opt(obj.opts[0])[1] else: default_string = str(default_value) else: - default_string = click.parser.split_opt(obj.secondary_opts[0])[1] + default_string = _split_opt(obj.secondary_opts[0])[1] # Typer override end elif ( isinstance(obj, TyperOption) @@ -166,13 +152,7 @@ def _extract_default_help_str( ctx.resilient_parsing = True try: - if _get_click_major() > 7: - default_value = obj.get_default(ctx, call=False) - else: - if inspect.isfunction(obj.default): - default_value = _("(dynamic)") - else: - default_value = obj.default + default_value = obj.get_default(ctx, call=False) finally: ctx.resilient_parsing = resilient return default_value @@ -201,23 +181,10 @@ def _main( args = list(args) if prog_name is None: - if _get_click_major() > 7: - prog_name = click.utils._detect_program_name() - else: - from click.utils import make_str - - prog_name = make_str( - os.path.basename(sys.argv[0] if sys.argv else __file__) - ) + prog_name = click.utils._detect_program_name() # Process shell completion requests and exit early. - if _get_click_major() > 7: - self._main_shell_completion(extra, prog_name, complete_var) - else: - completion_init() - from click.core import _bashcomplete # type: ignore - - _bashcomplete(self, prog_name, complete_var) + self._main_shell_completion(extra, prog_name, complete_var) try: try: @@ -315,27 +282,21 @@ def __init__( self.show_envvar = show_envvar self.hidden = hidden self.rich_help_panel = rich_help_panel - kwargs: Dict[str, Any] = { - "param_decls": param_decls, - "type": type, - "required": required, - "default": default, - "callback": callback, - "nargs": nargs, - "metavar": metavar, - "expose_value": expose_value, - "is_eager": is_eager, - "envvar": envvar, - } - if _get_click_major() > 7: - kwargs["shell_complete"] = shell_complete - else: - kwargs["autocompletion"] = autocompletion - super().__init__(**kwargs) - if _get_click_major() > 7: - _typer_param_setup_autocompletion_compat( - self, autocompletion=autocompletion - ) + + super().__init__( + param_decls=param_decls, + type=type, + required=required, + default=default, + callback=callback, + nargs=nargs, + metavar=metavar, + expose_value=expose_value, + is_eager=is_eager, + envvar=envvar, + shell_complete=shell_complete, + ) + _typer_param_setup_autocompletion_compat(self, autocompletion=autocompletion) def _get_default_string( self, @@ -417,11 +378,6 @@ def make_metavar(self) -> str: var += "..." return var - def shell_complete( - self, ctx: click.Context, incomplete: str - ) -> List["click.shell_completion.CompletionItem"]: - return _typer_param_shell_complete(self, ctx=ctx, incomplete=incomplete) - class TyperOption(click.core.Option): def __init__( @@ -463,43 +419,34 @@ def __init__( # Rich settings rich_help_panel: Union[str, None] = None, ): - # TODO: when deprecating Click 7, remove custom kwargs with prompt_required - # and call super().__init__() directly - kwargs: Dict[str, Any] = { - "param_decls": param_decls, - "type": type, - "required": required, - "default": default, - "callback": callback, - "nargs": nargs, - "metavar": metavar, - "expose_value": expose_value, - "is_eager": is_eager, - "envvar": envvar, - "show_default": show_default, - "prompt": prompt, - "confirmation_prompt": confirmation_prompt, - "hide_input": hide_input, - "is_flag": is_flag, - "flag_value": flag_value, - "multiple": multiple, - "count": count, - "allow_from_autoenv": allow_from_autoenv, - "help": help, - "hidden": hidden, - "show_choices": show_choices, - "show_envvar": show_envvar, - } - if _get_click_major() > 7: - kwargs["prompt_required"] = prompt_required - kwargs["shell_complete"] = shell_complete - else: - kwargs["autocompletion"] = autocompletion - super().__init__(**kwargs) - if _get_click_major() > 7: - _typer_param_setup_autocompletion_compat( - self, autocompletion=autocompletion - ) + super().__init__( + param_decls=param_decls, + type=type, + required=required, + default=default, + callback=callback, + nargs=nargs, + metavar=metavar, + expose_value=expose_value, + is_eager=is_eager, + envvar=envvar, + show_default=show_default, + prompt=prompt, + confirmation_prompt=confirmation_prompt, + hide_input=hide_input, + is_flag=is_flag, + flag_value=flag_value, + multiple=multiple, + count=count, + allow_from_autoenv=allow_from_autoenv, + help=help, + hidden=hidden, + show_choices=show_choices, + show_envvar=show_envvar, + prompt_required=prompt_required, + shell_complete=shell_complete, + ) + _typer_param_setup_autocompletion_compat(self, autocompletion=autocompletion) self.rich_help_panel = rich_help_panel def _get_default_string( @@ -522,9 +469,6 @@ def _extract_default_help_str( return _extract_default_help_str(self, ctx=ctx) def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]: - # Click 7.x was not breaking this use case, so in that case, re-use its logic - if _get_click_major() < 8: - return super().get_help_record(ctx) # Duplicate all of Click's logic only to modify a single line, to allow boolean # flags with only names for False values as it's currently supported by Typer # Ref: https://typer.tiangolo.com/tutorial/parameter-types/bool/#only-names-for-false @@ -609,11 +553,6 @@ def _write_opts(opts: Sequence[str]) -> str: return ("; " if any_prefix_is_slash else " / ").join(rv), help - def shell_complete( - self, ctx: click.Context, incomplete: str - ) -> List["click.shell_completion.CompletionItem"]: - return _typer_param_shell_complete(self, ctx=ctx, incomplete=incomplete) - def _typer_format_options( self: click.core.Command, *, ctx: click.Context, formatter: click.HelpFormatter diff --git a/typer/models.py b/typer/models.py index 9809a1c5a0..9bbe2a36d2 100644 --- a/typer/models.py +++ b/typer/models.py @@ -14,13 +14,9 @@ ) import click - -from ._compat_utils import _get_click_major +import click.shell_completion if TYPE_CHECKING: # pragma: no cover - if _get_click_major() > 7: - import click.shell_completion - from .core import TyperCommand, TyperGroup from .main import Typer diff --git a/typer/rich_utils.py b/typer/rich_utils.py index 51da5ca6ea..ff91e51662 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -383,19 +383,15 @@ def _print_options_panel( # Range - from # https://github.com/pallets/click/blob/c63c70dabd3f86ca68678b4f00951f78f52d0270/src/click/core.py#L2698-L2706 # noqa: E501 - try: - # skip count with default range type - if ( - isinstance(param.type, click.types._NumberRangeBase) - and isinstance(param, click.Option) - and not (param.count and param.type.min == 0 and param.type.max is None) - ): - range_str = param.type._describe_range() - if range_str: - metavar.append(RANGE_STRING.format(range_str)) - except AttributeError: # pragma: no cover - # click.types._NumberRangeBase is only in Click 8x onwards - pass + # skip count with default range type + if ( + isinstance(param.type, click.types._NumberRangeBase) + and isinstance(param, click.Option) + and not (param.count and param.type.min == 0 and param.type.max is None) + ): + range_str = param.type._describe_range() + if range_str: + metavar.append(RANGE_STRING.format(range_str)) # Required asterisk required: Union[str, Text] = "" @@ -621,7 +617,7 @@ def rich_format_help( console=console, ) - if isinstance(obj, click.MultiCommand): + if isinstance(obj, click.Group): panel_to_commands: DefaultDict[str, List[click.Command]] = defaultdict(list) for command_name in obj.list_commands(ctx): command = obj.get_command(ctx, command_name) From 0fc00e215683db3d4ccd7441af4c9c0cc5b7add4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 16:41:31 +0000 Subject: [PATCH 02/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index dfbde956d5..ad42592a7d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,7 @@ ### Breaking Changes +* 🔥 Remove support for Click 7, require Click 8+. PR [#760](https://github.com/tiangolo/typer/pull/760) by [@tiangolo](https://github.com/tiangolo). * 🔥 Remove support for Python 3.6. PR [#758](https://github.com/tiangolo/typer/pull/758) by [@tiangolo](https://github.com/tiangolo). ### Internal From 207e86881095ed384e3a7ef07b6bedae33ce4a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 16:24:22 -0500 Subject: [PATCH 03/37] =?UTF-8?q?=F0=9F=94=A7=20Refactor=20package=20manag?= =?UTF-8?q?er,=20move=20from=20Flit=20to=20PDM,=20remove=20private=20pip?= =?UTF-8?q?=20extras=20for=20`test`,=20`doc`,=20`dev`=20(#764)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 28 +++++++-------- .github/workflows/deploy-docs.yml | 4 +-- .github/workflows/publish.yml | 36 +++++++++++++------ .github/workflows/test.yml | 45 ++++++++++++++--------- pyproject.toml | 59 +++++++++++-------------------- requirements-docs.txt | 17 +++++++++ requirements-tests.txt | 10 ++++++ requirements.txt | 6 ++++ 8 files changed, 124 insertions(+), 81 deletions(-) create mode 100644 requirements-docs.txt create mode 100644 requirements-tests.txt create mode 100644 requirements.txt diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index bcd0e4e4a0..b8b2164354 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -17,9 +17,9 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@v3 - # For pull requests it's not necessary to checkout the code but for the main branch it is - - uses: dorny/paths-filter@v2 + - uses: actions/checkout@v4 + # For pull requests it's not necessary to checkout the code but for master it is + - uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -27,6 +27,7 @@ jobs: - README.md - docs/** - docs_src/** + - requirements-docs.txt - pyproject.toml - mkdocs.yml - mkdocs.insiders.yml @@ -43,25 +44,25 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.11" - uses: actions/cache@v3 id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v01 - - name: Install Flit - if: steps.cache.outputs.cache-hit != 'true' - run: python -m pip install flit + key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v01 - name: Install docs extras if: steps.cache.outputs.cache-hit != 'true' - run: python -m flit install --extras doc + run: pip install -r requirements-docs.txt - name: Install Material for MkDocs Insiders - if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true' - run: python -m pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git + if: ( github.event_name != 'pull_request' || github.secret_source != 'Actions' ) && steps.cache.outputs.cache-hit != 'true' + run: | + pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git + pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git + pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/mkdocstrings-python.git - uses: actions/cache@v3 with: key: mkdocs-cards-${{ github.ref }}-v1 @@ -70,10 +71,9 @@ jobs: if: github.event_name == 'pull_request' && github.secret_source != 'Actions' run: python -m mkdocs build - name: Build Docs with Insiders - if: github.event_name != 'pull_request' || github.secret_source == 'Actions' + if: ( github.event_name != 'pull_request' || github.secret_source != 'Actions' ) run: python -m mkdocs build --config-file mkdocs.insiders.yml - - uses: actions/upload-artifact@v3 with: name: docs-site diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index bca10dfdd6..8f526d818d 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -14,14 +14,14 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Clean site run: | rm -rf ./site mkdir ./site - name: Download Artifact Docs id: download - uses: dawidd6/action-download-artifact@v2.27.0 + uses: dawidd6/action-download-artifact@v3.1.4 with: if_no_artifact_found: ignore github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1786d2dbb5..bc72a0ed72 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,17 +9,33 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" + # cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + id: cache with: - python-version: "3.7" - - name: Install Flit - run: pip install flit - - name: Install Dependencies - run: flit install --symlink + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }} + - name: Install build dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: pip install build + - name: Build distribution + run: python -m build - name: Publish + uses: pypa/gh-action-pypi-publish@v1.8.11 + with: + password: ${{ secrets.PYPI_API_TOKEN }} + - name: Dump GitHub context env: - FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }} - FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }} - run: bash scripts/publish.sh + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 533c4cf417..8fcc70910e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,26 +5,38 @@ on: branches: - master pull_request: - types: [opened, synchronize] + types: + - opened + - synchronize jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: matrix: python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] fail-fast: false - steps: - - uses: actions/checkout@v3 + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install Flit - run: pip install flit + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" + # cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }} - name: Install Dependencies - run: python -m flit install --symlink + if: steps.cache.outputs.cache-hit != 'true' + run: pip install -r requirements-tests.txt - name: Lint run: bash scripts/lint.sh - run: mkdir coverage @@ -42,27 +54,28 @@ jobs: coverage-combine: needs: [test] runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-python@v4 + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.8' - + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" + # cache-dependency-path: pyproject.toml - name: Get coverage files uses: actions/download-artifact@v3 with: name: coverage path: coverage - - run: pip install coverage[toml] - - run: ls -la coverage - run: coverage combine coverage - run: coverage report - run: coverage html --show-contexts --title "Coverage for ${{ github.sha }}" - - name: Store coverage HTML uses: actions/upload-artifact@v3 with: diff --git a/pyproject.toml b/pyproject.toml index c6e282a545..7e40e94256 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,16 @@ [build-system] -requires = ["flit_core >=2,<3"] -build-backend = "flit_core.buildapi" +requires = ["pdm-backend"] +build-backend = "pdm.backend" -[tool.flit.metadata] -module = "typer" -author = "Sebastián Ramírez" -author-email = "tiangolo@gmail.com" -home-page = "https://github.com/tiangolo/typer" +[project] +name = "typer" +dynamic = ["version"] +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +authors = [ + {name = "Sebastián Ramírez", email = "tiangolo@gmail.com"}, +] +readme = "README.md" +requires-python = ">=3.7" classifiers = [ "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", @@ -26,49 +30,27 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", - "License :: OSI Approved :: MIT License" - ] -requires = [ + "License :: OSI Approved :: MIT License", +] +dependencies = [ "click >= 8.0.0", "typing-extensions >= 3.7.4.3", ] -description-file = "README.md" -requires-python = ">=3.7" -[tool.flit.metadata.urls] +[project.urls] Documentation = "https://typer.tiangolo.com/" +homepage = "https://github.com/tiangolo/typer" -[tool.flit.metadata.requires-extra] -test = [ - "shellingham >=1.3.0,<2.0.0", - "pytest >=4.4.0,<8.0.0", - "pytest-cov >=2.10.0,<5.0.0", - "coverage >=6.2,<7.0", - "pytest-xdist >=1.32.0,<4.0.0", - "pytest-sugar >=0.9.4,<0.10.0", - "mypy ==0.971", - "black >=22.3.0,<23.0.0", - "isort >=5.0.6,<6.0.0", - "rich >=10.11.0,<14.0.0", -] -doc = [ - "mkdocs >=1.1.2,<2.0.0", - "mkdocs-material >=8.1.4,<9.0.0", - "mdx-include >=1.4.1,<2.0.0", - "pillow >=9.3.0,<10.0.0", - "cairosvg >=2.5.2,<3.0.0", -] -dev = [ - "autoflake >=1.3.1,<2.0.0", - "flake8 >=3.8.3,<4.0.0", - "pre-commit >=2.17.0,<3.0.0", -] +[project.optional-dependencies] all = [ "colorama >=0.4.3,<0.5.0", "shellingham >=1.3.0,<2.0.0", "rich >=10.11.0,<14.0.0", ] +[tool.pdm] +version = { source = "file", path = "typer/__init__.py" } + [tool.isort] profile = "black" known_third_party = ["typer", "click"] @@ -89,7 +71,6 @@ filterwarnings = [ "error", # TODO: until I refactor completion to use the new shell_complete "ignore:'autocompletion' is renamed to 'shell_complete'. The old name is deprecated and will be removed in Click 8.1. See the docs about 'Parameter' for information about new behavior.:DeprecationWarning:typer", - 'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', # For pytest-xdist 'ignore::DeprecationWarning:xdist', ] diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000000..bad2afad2a --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,17 @@ +-e . + +mkdocs-material==9.4.7 +mdx-include >=1.4.1,<2.0.0 +mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0 +mkdocs-redirects>=1.2.1,<1.3.0 +pyyaml >=5.3.1,<7.0.0 +# For Material for MkDocs, Chinese search +jieba==0.42.1 +# For image processing by Material for MkDocs +pillow==10.1.0 +# For image processing by Material for MkDocs +cairosvg==2.7.0 +mkdocstrings[python]==0.23.0 +griffe-typingdoc==0.2.2 +# For griffe, it formats with black +black==23.3.0 diff --git a/requirements-tests.txt b/requirements-tests.txt new file mode 100644 index 0000000000..e7850a4c06 --- /dev/null +++ b/requirements-tests.txt @@ -0,0 +1,10 @@ +-e .[all] + +pytest >=4.4.0,<8.0.0 +pytest-cov >=2.10.0,<5.0.0 +coverage[toml] >=6.2,<7.0 +pytest-xdist >=1.32.0,<4.0.0 +pytest-sugar >=0.9.4,<0.10.0 +mypy ==0.971 +black >=22.3.0,<23.0.0 +isort >=5.0.6,<6.0.0 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..d84d26a8da --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +-e .[all] + +-r requirements-tests.txt +-r requirements-docs.txt + +pre-commit >=2.17.0,<4.0.0 From 333acc2e10c8e30f9ceec2804b2ade8e22a49dee Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 21:24:41 +0000 Subject: [PATCH 04/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index ad42592a7d..78663f9cf1 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,7 @@ ### Breaking Changes +* 🔧 Refactor package manager, move from Flit to PDM, remove private pip extras for `test`, `doc`, `dev`. PR [#764](https://github.com/tiangolo/typer/pull/764) by [@tiangolo](https://github.com/tiangolo). * 🔥 Remove support for Click 7, require Click 8+. PR [#760](https://github.com/tiangolo/typer/pull/760) by [@tiangolo](https://github.com/tiangolo). * 🔥 Remove support for Python 3.6. PR [#758](https://github.com/tiangolo/typer/pull/758) by [@tiangolo](https://github.com/tiangolo). From 6cd35ecc0619ce528e318cf8fb58536e9bc33b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 16:29:29 -0500 Subject: [PATCH 05/37] =?UTF-8?q?=F0=9F=91=B7=20Upgrade=20issue-manager=20?= =?UTF-8?q?GitHub=20Action=20(#765)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-manager.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index 69fce64d4a..31bf065b01 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -2,25 +2,38 @@ name: Issue Manager on: schedule: - - cron: "0 0 * * *" + - cron: "10 4 * * *" issue_comment: types: - created - - edited issues: types: - labeled + pull_request_target: + types: + - labeled + workflow_dispatch: jobs: issue-manager: + if: github.repository_owner == 'tiangolo' runs-on: ubuntu-latest steps: - - uses: tiangolo/issue-manager@0.4.0 + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: tiangolo/issue-manager@0.5.0 with: token: ${{ secrets.GITHUB_TOKEN }} config: > { "answered": { - "message": "Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues." + "delay": 864000, + "message": "Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs." + }, + "changes-requested": { + "delay": 2628000, + "message": "As this PR had requested changes to be applied but has been inactive for a while, it's now going to be closed. But if there's anyone interested, feel free to create a new PR." } } From 13d5240b510e465ed3d008528a488c7035afa774 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 21:29:48 +0000 Subject: [PATCH 06/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 78663f9cf1..f53655ba5d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ ### Internal +* 👷 Upgrade issue-manager GitHub Action. PR [#765](https://github.com/tiangolo/typer/pull/765) by [@tiangolo](https://github.com/tiangolo). * 👷 Add alls-green to CI. PR [#759](https://github.com/tiangolo/typer/pull/759) by [@tiangolo](https://github.com/tiangolo). ## 0.10.0 From 63978a73bbf362df7a9f5f45d83b2fd0155803ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 16:30:53 -0500 Subject: [PATCH 07/37] =?UTF-8?q?=F0=9F=91=B7=20Upgrade=20latest-changes?= =?UTF-8?q?=20GitHub=20Action=20(#766)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/latest-changes.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 61a41e7977..31c4ea724b 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -20,6 +20,10 @@ jobs: latest-changes: runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v4 with: # To allow latest-changes to commit to the main branch @@ -30,7 +34,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: docker://tiangolo/latest-changes:0.2.0 + - uses: docker://tiangolo/latest-changes:0.3.0 # - uses: tiangolo/latest-changes@main with: token: ${{ secrets.GITHUB_TOKEN }} From f5e7f46ecd6498c09714edab304ac79d25f852c2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 21:31:14 +0000 Subject: [PATCH 08/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index f53655ba5d..56d27f9fe8 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ ### Internal +* 👷 Upgrade latest-changes GitHub Action. PR [#766](https://github.com/tiangolo/typer/pull/766) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade issue-manager GitHub Action. PR [#765](https://github.com/tiangolo/typer/pull/765) by [@tiangolo](https://github.com/tiangolo). * 👷 Add alls-green to CI. PR [#759](https://github.com/tiangolo/typer/pull/759) by [@tiangolo](https://github.com/tiangolo). From 1333eab1e3c9cfe9e0e127375998417e2a8e4413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 16:32:54 -0500 Subject: [PATCH 09/37] =?UTF-8?q?=F0=9F=91=B7=20Upgrade=20Smokeshow=20GitH?= =?UTF-8?q?ub=20action=20(#767)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/smokeshow.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 421720433f..7afe2c0d9f 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -14,13 +14,17 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v4 + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/setup-python@v5 with: python-version: '3.9' - run: pip install smokeshow - - uses: dawidd6/action-download-artifact@v2.26.0 + - uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: test.yml commit: ${{ github.event.workflow_run.head_sha }} From 3eccf5adcce3c003aa9fc36561897f0323f302d6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 21:33:16 +0000 Subject: [PATCH 10/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 56d27f9fe8..1563c17dfa 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ ### Internal +* 👷 Upgrade Smokeshow GitHub action. PR [#767](https://github.com/tiangolo/typer/pull/767) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade latest-changes GitHub Action. PR [#766](https://github.com/tiangolo/typer/pull/766) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade issue-manager GitHub Action. PR [#765](https://github.com/tiangolo/typer/pull/765) by [@tiangolo](https://github.com/tiangolo). * 👷 Add alls-green to CI. PR [#759](https://github.com/tiangolo/typer/pull/759) by [@tiangolo](https://github.com/tiangolo). From 38b8e4a0220171a25426d7579f8309655f0a5033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 16:45:22 -0500 Subject: [PATCH 11/37] =?UTF-8?q?=F0=9F=94=A7=20Migrate=20from=20Black,=20?= =?UTF-8?q?isort,=20flake8,=20autoflake,=20pyupgrade=20to=20Ruff=20(#763)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 40 ++------------- docs_src/arguments/envvar/tutorial002_an.py | 2 +- docs_src/arguments/envvar/tutorial003_an.py | 2 +- docs_src/arguments/help/tutorial004_an.py | 2 +- docs_src/arguments/help/tutorial005.py | 2 +- docs_src/arguments/help/tutorial005_an.py | 2 +- docs_src/commands/help/tutorial001.py | 2 +- docs_src/commands/help/tutorial001_an.py | 2 +- docs_src/commands/help/tutorial004.py | 2 +- docs_src/commands/help/tutorial004_an.py | 2 +- docs_src/commands/help/tutorial005_an.py | 2 +- docs_src/commands/options/tutorial001.py | 4 +- docs_src/commands/options/tutorial001_an.py | 2 +- .../tutorial002.py | 2 +- .../tutorial002_an.py | 2 +- docs_src/options/help/tutorial004.py | 2 +- docs_src/options/help/tutorial004_an.py | 2 +- docs_src/options/prompt/tutorial003_an.py | 2 +- .../options_autocompletion/tutorial002.py | 2 +- .../options_autocompletion/tutorial003.py | 2 +- .../options_autocompletion/tutorial004.py | 2 +- .../options_autocompletion/tutorial005.py | 2 +- .../options_autocompletion/tutorial006_an.py | 2 +- .../options_autocompletion/tutorial007.py | 2 +- .../options_autocompletion/tutorial008.py | 2 +- .../options_autocompletion/tutorial009.py | 2 +- .../parameter_types/datetime/tutorial002.py | 2 +- .../datetime/tutorial002_an.py | 2 +- docs_src/parameter_types/enum/tutorial002.py | 2 +- .../parameter_types/enum/tutorial002_an.py | 2 +- docs_src/parameter_types/path/tutorial002.py | 2 +- .../parameter_types/path/tutorial002_an.py | 2 +- pyproject.toml | 50 +++++++++++++++++++ requirements-tests.txt | 3 +- scripts/format.sh | 6 +-- scripts/lint.sh | 4 +- tests/test_ambiguous_params.py | 48 ++++++++++-------- tests/test_compat/test_option_get_help.py | 3 +- tests/test_completion/test_completion.py | 30 ++++------- .../test_completion_complete.py | 30 ++++------- .../test_completion_complete_no_help.py | 12 ++--- .../test_completion_install.py | 14 ++---- tests/test_completion/test_completion_show.py | 18 +++---- tests/test_others.py | 14 ++---- tests/test_prog_name.py | 3 +- tests/test_tracebacks.py | 9 ++-- .../test_default/test_tutorial001.py | 3 +- .../test_default/test_tutorial001_an.py | 3 +- .../test_default/test_tutorial002.py | 5 +- .../test_default/test_tutorial002_an.py | 5 +- .../test_envvar/test_tutorial001.py | 3 +- .../test_envvar/test_tutorial001_an.py | 3 +- .../test_envvar/test_tutorial002.py | 3 +- .../test_envvar/test_tutorial002_an.py | 3 +- .../test_envvar/test_tutorial003.py | 3 +- .../test_envvar/test_tutorial003_an.py | 3 +- .../test_help/test_tutorial001.py | 3 +- .../test_help/test_tutorial001_an.py | 3 +- .../test_help/test_tutorial002.py | 3 +- .../test_help/test_tutorial002_an.py | 3 +- .../test_help/test_tutorial003.py | 3 +- .../test_help/test_tutorial003_an.py | 3 +- .../test_help/test_tutorial004.py | 3 +- .../test_help/test_tutorial004_an.py | 3 +- .../test_help/test_tutorial005.py | 3 +- .../test_help/test_tutorial005_an.py | 3 +- .../test_help/test_tutorial006.py | 3 +- .../test_help/test_tutorial006_an.py | 3 +- .../test_help/test_tutorial007.py | 3 +- .../test_help/test_tutorial007_an.py | 3 +- .../test_help/test_tutorial008.py | 3 +- .../test_help/test_tutorial008_an.py | 3 +- .../test_optional/test_tutorial001.py | 3 +- .../test_optional/test_tutorial001_an.py | 3 +- .../test_optional/test_tutorial002.py | 3 +- .../test_optional/test_tutorial002_an.py | 3 +- .../test_optional/test_tutorial003.py | 3 +- .../test_arguments/test_tutorial001.py | 3 +- .../test_callback/test_tutorial001.py | 3 +- .../test_callback/test_tutorial002.py | 3 +- .../test_callback/test_tutorial003.py | 3 +- .../test_callback/test_tutorial004.py | 3 +- .../test_context/test_tutorial001.py | 3 +- .../test_context/test_tutorial002.py | 3 +- .../test_context/test_tutorial003.py | 3 +- .../test_context/test_tutorial004.py | 3 +- .../test_help/test_tutorial001.py | 3 +- .../test_help/test_tutorial001_an.py | 3 +- .../test_help/test_tutorial002.py | 3 +- .../test_help/test_tutorial003.py | 3 +- .../test_help/test_tutorial004.py | 3 +- .../test_help/test_tutorial004_an.py | 3 +- .../test_help/test_tutorial005.py | 3 +- .../test_help/test_tutorial005_an.py | 3 +- .../test_help/test_tutorial006.py | 3 +- .../test_help/test_tutorial007.py | 3 +- .../test_help/test_tutorial007_an.py | 3 +- .../test_help/test_tutorial008.py | 3 +- .../test_index/test_tutorial001.py | 3 +- .../test_index/test_tutorial002.py | 3 +- .../test_index/test_tutorial003.py | 3 +- .../test_name/test_tutorial001.py | 3 +- .../test_one_or_multiple/test_tutorial001.py | 3 +- .../test_one_or_multiple/test_tutorial002.py | 3 +- .../test_options/test_tutorial001.py | 3 +- .../test_options/test_tutorial001_an.py | 3 +- .../test_exceptions/test_tutorial001.py | 9 ++-- .../test_exceptions/test_tutorial002.py | 9 ++-- .../test_exceptions/test_tutorial003.py | 6 +-- .../test_exceptions/test_tutorial004.py | 6 +-- .../test_first_steps/test_tutorial001.py | 3 +- .../test_first_steps/test_tutorial002.py | 3 +- .../test_first_steps/test_tutorial003.py | 3 +- .../test_first_steps/test_tutorial004.py | 3 +- .../test_first_steps/test_tutorial005.py | 3 +- .../test_first_steps/test_tutorial006.py | 3 +- .../test_tutorial001.py | 3 +- .../test_tutorial002.py | 3 +- .../test_tutorial002_an.py | 3 +- .../test_multiple_options/test_tutorial001.py | 3 +- .../test_tutorial001_an.py | 3 +- .../test_multiple_options/test_tutorial002.py | 3 +- .../test_tutorial002_an.py | 3 +- .../test_tutorial001.py | 3 +- .../test_tutorial001_an.py | 3 +- .../test_callback/test_tutorial001.py | 3 +- .../test_callback/test_tutorial001_an.py | 3 +- .../test_callback/test_tutorial003.py | 6 +-- .../test_callback/test_tutorial003_an.py | 6 +-- .../test_callback/test_tutorial004.py | 6 +-- .../test_callback/test_tutorial004_an.py | 6 +-- .../test_help/test_tutorial001.py | 3 +- .../test_help/test_tutorial001_an.py | 3 +- .../test_help/test_tutorial002.py | 3 +- .../test_help/test_tutorial002_an.py | 3 +- .../test_help/test_tutorial003.py | 3 +- .../test_help/test_tutorial003_an.py | 3 +- .../test_name/test_tutorial001.py | 3 +- .../test_name/test_tutorial001_an.py | 3 +- .../test_name/test_tutorial002.py | 3 +- .../test_name/test_tutorial002_an.py | 3 +- .../test_name/test_tutorial003.py | 3 +- .../test_name/test_tutorial003_an.py | 3 +- .../test_name/test_tutorial004.py | 3 +- .../test_name/test_tutorial004_an.py | 3 +- .../test_name/test_tutorial005.py | 3 +- .../test_name/test_tutorial005_an.py | 3 +- .../test_prompt/test_tutorial001.py | 3 +- .../test_prompt/test_tutorial001_an.py | 3 +- .../test_prompt/test_tutorial002.py | 3 +- .../test_prompt/test_tutorial002_an.py | 3 +- .../test_prompt/test_tutorial003.py | 3 +- .../test_prompt/test_tutorial003_an.py | 3 +- .../test_required/test_tutorial001.py | 3 +- .../test_required/test_tutorial001_an.py | 3 +- .../test_version/test_tutorial003.py | 6 +-- .../test_version/test_tutorial003_an.py | 6 +-- .../test_tutorial002.py | 6 +-- .../test_tutorial002_an.py | 6 +-- .../test_tutorial003.py | 6 +-- .../test_tutorial003_an.py | 6 +-- .../test_tutorial004.py | 6 +-- .../test_tutorial004_an.py | 6 +-- .../test_tutorial007.py | 6 +-- .../test_tutorial007_an.py | 6 +-- .../test_tutorial008.py | 6 +-- .../test_tutorial008_an.py | 6 +-- .../test_tutorial009.py | 6 +-- .../test_tutorial009_an.py | 6 +-- .../test_bool/test_tutorial001.py | 3 +- .../test_bool/test_tutorial001_an.py | 3 +- .../test_bool/test_tutorial002.py | 3 +- .../test_bool/test_tutorial002_an.py | 3 +- .../test_bool/test_tutorial003.py | 3 +- .../test_bool/test_tutorial003_an.py | 3 +- .../test_bool/test_tutorial004.py | 3 +- .../test_bool/test_tutorial004_an.py | 3 +- .../test_custom_types/test_tutorial001.py | 3 +- .../test_custom_types/test_tutorial001_an.py | 3 +- .../test_custom_types/test_tutorial002.py | 3 +- .../test_custom_types/test_tutorial002_an.py | 3 +- .../test_datetime/test_tutorial001.py | 3 +- .../test_datetime/test_tutorial002.py | 3 +- .../test_datetime/test_tutorial002_an.py | 3 +- .../test_enum/test_tutorial001.py | 3 +- .../test_enum/test_tutorial002.py | 3 +- .../test_enum/test_tutorial002_an.py | 3 +- .../test_enum/test_tutorial003.py | 3 +- .../test_enum/test_tutorial003_an.py | 3 +- .../test_file/test_tutorial001.py | 3 +- .../test_file/test_tutorial001_an.py | 3 +- .../test_file/test_tutorial002.py | 3 +- .../test_file/test_tutorial002_an.py | 3 +- .../test_file/test_tutorial003.py | 3 +- .../test_file/test_tutorial003_an.py | 3 +- .../test_file/test_tutorial004.py | 3 +- .../test_file/test_tutorial004_an.py | 3 +- .../test_file/test_tutorial005.py | 3 +- .../test_file/test_tutorial005_an.py | 3 +- .../test_index/test_tutorial001.py | 3 +- .../test_number/test_tutorial001.py | 3 +- .../test_number/test_tutorial001_an.py | 3 +- .../test_number/test_tutorial002.py | 3 +- .../test_number/test_tutorial002_an.py | 3 +- .../test_number/test_tutorial003.py | 3 +- .../test_number/test_tutorial003_an.py | 3 +- .../test_path/test_tutorial001.py | 3 +- .../test_path/test_tutorial001_an.py | 3 +- .../test_path/test_tutorial002.py | 3 +- .../test_path/test_tutorial002_an.py | 3 +- .../test_uuid/test_tutorial001.py | 3 +- .../test_prompt/test_tutorial001.py | 3 +- .../test_prompt/test_tutorial002.py | 3 +- .../test_prompt/test_tutorial003.py | 3 +- .../test_tutorial001.py | 3 +- .../test_tutorial002.py | 3 +- .../test_tutorial003.py | 3 +- .../test_tutorial004.py | 3 +- .../test_name_help/test_tutorial001.py | 3 +- .../test_name_help/test_tutorial002.py | 3 +- .../test_name_help/test_tutorial003.py | 3 +- .../test_name_help/test_tutorial004.py | 3 +- .../test_name_help/test_tutorial005.py | 3 +- .../test_name_help/test_tutorial006.py | 3 +- .../test_name_help/test_tutorial007.py | 3 +- .../test_name_help/test_tutorial008.py | 3 +- .../test_subcommands/test_tutorial001.py | 5 +- .../test_subcommands/test_tutorial002.py | 3 +- .../test_subcommands/test_tutorial003.py | 3 +- .../test_terminating/test_tutorial001.py | 3 +- .../test_terminating/test_tutorial002.py | 3 +- .../test_terminating/test_tutorial003.py | 3 +- .../test_tutorial/test_testing/test_app01.py | 3 +- .../test_tutorial/test_testing/test_app02.py | 3 +- .../test_testing/test_app02_an.py | 3 +- .../test_tutorial/test_testing/test_app03.py | 3 +- .../test_using_click/test_tutorial003.py | 3 +- .../test_using_click/test_tutorial004.py | 3 +- tests/test_type_conversion.py | 4 +- typer/_completion_shared.py | 12 ++--- typer/_typing.py | 2 +- typer/core.py | 6 +-- typer/main.py | 31 ++++++------ 243 files changed, 414 insertions(+), 643 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 673e98b067..3289dd0950 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,43 +13,13 @@ repos: - --unsafe - id: end-of-file-fixer - id: trailing-whitespace -- repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.0 hooks: - - id: pyupgrade + - id: ruff args: - - --py3-plus - - --keep-runtime-typing - # This file is more readable without yield from - exclude: ^docs_src/progressbar/tutorial004\.py -- repo: https://github.com/PyCQA/autoflake - rev: v2.2.1 - hooks: - - id: autoflake - args: - - --recursive - - --in-place - - --remove-all-unused-imports - - --remove-unused-variables - - --expand-star-imports - - --exclude - - __init__.py - - --remove-duplicate-keys -- repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - name: isort (python) - - id: isort - name: isort (cython) - types: [cython] - - id: isort - name: isort (pyi) - types: [pyi] -- repo: https://github.com/psf/black - rev: 23.10.0 - hooks: - - id: black + - --fix + - id: ruff-format ci: autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate diff --git a/docs_src/arguments/envvar/tutorial002_an.py b/docs_src/arguments/envvar/tutorial002_an.py index f5373e134a..ebc5575ef0 100644 --- a/docs_src/arguments/envvar/tutorial002_an.py +++ b/docs_src/arguments/envvar/tutorial002_an.py @@ -3,7 +3,7 @@ def main( - name: Annotated[str, typer.Argument(envvar=["AWESOME_NAME", "GOD_NAME"])] = "World" + name: Annotated[str, typer.Argument(envvar=["AWESOME_NAME", "GOD_NAME"])] = "World", ): print(f"Hello Mr. {name}") diff --git a/docs_src/arguments/envvar/tutorial003_an.py b/docs_src/arguments/envvar/tutorial003_an.py index 8cb29195a9..76205d2539 100644 --- a/docs_src/arguments/envvar/tutorial003_an.py +++ b/docs_src/arguments/envvar/tutorial003_an.py @@ -5,7 +5,7 @@ def main( name: Annotated[ str, typer.Argument(envvar="AWESOME_NAME", show_envvar=False) - ] = "World" + ] = "World", ): print(f"Hello Mr. {name}") diff --git a/docs_src/arguments/help/tutorial004_an.py b/docs_src/arguments/help/tutorial004_an.py index 7338d06754..86f7e2e3a5 100644 --- a/docs_src/arguments/help/tutorial004_an.py +++ b/docs_src/arguments/help/tutorial004_an.py @@ -5,7 +5,7 @@ def main( name: Annotated[ str, typer.Argument(help="Who to greet", show_default=False) - ] = "World" + ] = "World", ): """ Say hi to NAME very gently, like Dirk. diff --git a/docs_src/arguments/help/tutorial005.py b/docs_src/arguments/help/tutorial005.py index 55b66b9715..0419a4e352 100644 --- a/docs_src/arguments/help/tutorial005.py +++ b/docs_src/arguments/help/tutorial005.py @@ -4,7 +4,7 @@ def main( name: str = typer.Argument( "Wade Wilson", help="Who to greet", show_default="Deadpoolio the amazing's name" - ) + ), ): print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial005_an.py b/docs_src/arguments/help/tutorial005_an.py index 394f54e38f..f61e8b6dcf 100644 --- a/docs_src/arguments/help/tutorial005_an.py +++ b/docs_src/arguments/help/tutorial005_an.py @@ -8,7 +8,7 @@ def main( typer.Argument( help="Who to greet", show_default="Deadpoolio the amazing's name" ), - ] = "Wade Wilson" + ] = "Wade Wilson", ): print(f"Hello {name}") diff --git a/docs_src/commands/help/tutorial001.py b/docs_src/commands/help/tutorial001.py index dda530655d..90726a0b13 100644 --- a/docs_src/commands/help/tutorial001.py +++ b/docs_src/commands/help/tutorial001.py @@ -37,7 +37,7 @@ def delete_all( ..., prompt="Are you sure you want to delete ALL users?", help="Force deletion without confirmation.", - ) + ), ): """ Delete ALL users in the database. diff --git a/docs_src/commands/help/tutorial001_an.py b/docs_src/commands/help/tutorial001_an.py index a7736da05c..748655327c 100644 --- a/docs_src/commands/help/tutorial001_an.py +++ b/docs_src/commands/help/tutorial001_an.py @@ -42,7 +42,7 @@ def delete_all( prompt="Are you sure you want to delete ALL users?", help="Force deletion without confirmation.", ), - ] + ], ): """ Delete ALL users in the database. diff --git a/docs_src/commands/help/tutorial004.py b/docs_src/commands/help/tutorial004.py index 956ddc0d53..1e07817329 100644 --- a/docs_src/commands/help/tutorial004.py +++ b/docs_src/commands/help/tutorial004.py @@ -7,7 +7,7 @@ def create( username: str = typer.Argument( ..., help="The username to be [green]created[/green]" - ) + ), ): """ [bold green]Create[/bold green] a new [italic]shiny[/italic] user. :sparkles: diff --git a/docs_src/commands/help/tutorial004_an.py b/docs_src/commands/help/tutorial004_an.py index d4bad589eb..e5c40e58ee 100644 --- a/docs_src/commands/help/tutorial004_an.py +++ b/docs_src/commands/help/tutorial004_an.py @@ -8,7 +8,7 @@ def create( username: Annotated[ str, typer.Argument(help="The username to be [green]created[/green]") - ] + ], ): """ [bold green]Create[/bold green] a new [italic]shinny[/italic] user. :sparkles: diff --git a/docs_src/commands/help/tutorial005_an.py b/docs_src/commands/help/tutorial005_an.py index 208d97e680..020d4ed85f 100644 --- a/docs_src/commands/help/tutorial005_an.py +++ b/docs_src/commands/help/tutorial005_an.py @@ -6,7 +6,7 @@ @app.command() def create( - username: Annotated[str, typer.Argument(help="The username to be **created**")] + username: Annotated[str, typer.Argument(help="The username to be **created**")], ): """ **Create** a new *shinny* user. :sparkles: diff --git a/docs_src/commands/options/tutorial001.py b/docs_src/commands/options/tutorial001.py index bdc795f520..b8dccd5e71 100644 --- a/docs_src/commands/options/tutorial001.py +++ b/docs_src/commands/options/tutorial001.py @@ -21,7 +21,9 @@ def delete( @app.command() def delete_all( - force: bool = typer.Option(..., prompt="Are you sure you want to delete ALL users?") + force: bool = typer.Option( + ..., prompt="Are you sure you want to delete ALL users?" + ), ): if force: print("Deleting all users") diff --git a/docs_src/commands/options/tutorial001_an.py b/docs_src/commands/options/tutorial001_an.py index bafc4543ca..5d0e1e47e7 100644 --- a/docs_src/commands/options/tutorial001_an.py +++ b/docs_src/commands/options/tutorial001_an.py @@ -26,7 +26,7 @@ def delete( def delete_all( force: Annotated[ bool, typer.Option(prompt="Are you sure you want to delete ALL users?") - ] + ], ): if force: print("Deleting all users") diff --git a/docs_src/multiple_values/arguments_with_multiple_values/tutorial002.py b/docs_src/multiple_values/arguments_with_multiple_values/tutorial002.py index c7003f35d9..8c1e74c227 100644 --- a/docs_src/multiple_values/arguments_with_multiple_values/tutorial002.py +++ b/docs_src/multiple_values/arguments_with_multiple_values/tutorial002.py @@ -6,7 +6,7 @@ def main( names: Tuple[str, str, str] = typer.Argument( ("Harry", "Hermione", "Ron"), help="Select 3 characters to play with" - ) + ), ): for name in names: print(f"Hello {name}") diff --git a/docs_src/multiple_values/arguments_with_multiple_values/tutorial002_an.py b/docs_src/multiple_values/arguments_with_multiple_values/tutorial002_an.py index 7ef3af7e51..46d1a5e208 100644 --- a/docs_src/multiple_values/arguments_with_multiple_values/tutorial002_an.py +++ b/docs_src/multiple_values/arguments_with_multiple_values/tutorial002_an.py @@ -7,7 +7,7 @@ def main( names: Annotated[ Tuple[str, str, str], typer.Argument(help="Select 3 characters to play with") - ] = ("Harry", "Hermione", "Ron") + ] = ("Harry", "Hermione", "Ron"), ): for name in names: print(f"Hello {name}") diff --git a/docs_src/options/help/tutorial004.py b/docs_src/options/help/tutorial004.py index 9aa3e42e14..2faff3fb47 100644 --- a/docs_src/options/help/tutorial004.py +++ b/docs_src/options/help/tutorial004.py @@ -4,7 +4,7 @@ def main( fullname: str = typer.Option( "Wade Wilson", show_default="Deadpoolio the amazing's name" - ) + ), ): print(f"Hello {fullname}") diff --git a/docs_src/options/help/tutorial004_an.py b/docs_src/options/help/tutorial004_an.py index 8913573637..f3b53f2c56 100644 --- a/docs_src/options/help/tutorial004_an.py +++ b/docs_src/options/help/tutorial004_an.py @@ -5,7 +5,7 @@ def main( fullname: Annotated[ str, typer.Option(show_default="Deadpoolio the amazing's name") - ] = "Wade Wilson" + ] = "Wade Wilson", ): print(f"Hello {fullname}") diff --git a/docs_src/options/prompt/tutorial003_an.py b/docs_src/options/prompt/tutorial003_an.py index 63e9097894..c12d1add77 100644 --- a/docs_src/options/prompt/tutorial003_an.py +++ b/docs_src/options/prompt/tutorial003_an.py @@ -3,7 +3,7 @@ def main( - project_name: Annotated[str, typer.Option(prompt=True, confirmation_prompt=True)] + project_name: Annotated[str, typer.Option(prompt=True, confirmation_prompt=True)], ): print(f"Deleting project {project_name}") diff --git a/docs_src/options_autocompletion/tutorial002.py b/docs_src/options_autocompletion/tutorial002.py index 8b18760d47..6c14a97ce4 100644 --- a/docs_src/options_autocompletion/tutorial002.py +++ b/docs_src/options_autocompletion/tutorial002.py @@ -12,7 +12,7 @@ def complete_name(): def main( name: str = typer.Option( "World", help="The name to say hi to.", autocompletion=complete_name - ) + ), ): print(f"Hello {name}") diff --git a/docs_src/options_autocompletion/tutorial003.py b/docs_src/options_autocompletion/tutorial003.py index b2fe534028..9af41f23b5 100644 --- a/docs_src/options_autocompletion/tutorial003.py +++ b/docs_src/options_autocompletion/tutorial003.py @@ -18,7 +18,7 @@ def complete_name(incomplete: str): def main( name: str = typer.Option( "World", help="The name to say hi to.", autocompletion=complete_name - ) + ), ): print(f"Hello {name}") diff --git a/docs_src/options_autocompletion/tutorial004.py b/docs_src/options_autocompletion/tutorial004.py index 9bb08dd196..3be0cf35db 100644 --- a/docs_src/options_autocompletion/tutorial004.py +++ b/docs_src/options_autocompletion/tutorial004.py @@ -23,7 +23,7 @@ def complete_name(incomplete: str): def main( name: str = typer.Option( "World", help="The name to say hi to.", autocompletion=complete_name - ) + ), ): print(f"Hello {name}") diff --git a/docs_src/options_autocompletion/tutorial005.py b/docs_src/options_autocompletion/tutorial005.py index d6efb4fe14..10ac532ad2 100644 --- a/docs_src/options_autocompletion/tutorial005.py +++ b/docs_src/options_autocompletion/tutorial005.py @@ -20,7 +20,7 @@ def complete_name(incomplete: str): def main( name: str = typer.Option( "World", help="The name to say hi to.", autocompletion=complete_name - ) + ), ): print(f"Hello {name}") diff --git a/docs_src/options_autocompletion/tutorial006_an.py b/docs_src/options_autocompletion/tutorial006_an.py index ae208105b0..46319c2ecd 100644 --- a/docs_src/options_autocompletion/tutorial006_an.py +++ b/docs_src/options_autocompletion/tutorial006_an.py @@ -8,7 +8,7 @@ @app.command() def main( - name: Annotated[List[str], typer.Option(help="The name to say hi to.")] = ["World"] + name: Annotated[List[str], typer.Option(help="The name to say hi to.")] = ["World"], ): for each_name in name: print(f"Hello {each_name}") diff --git a/docs_src/options_autocompletion/tutorial007.py b/docs_src/options_autocompletion/tutorial007.py index c60dfe95de..7c56ac7549 100644 --- a/docs_src/options_autocompletion/tutorial007.py +++ b/docs_src/options_autocompletion/tutorial007.py @@ -23,7 +23,7 @@ def complete_name(ctx: typer.Context, incomplete: str): def main( name: List[str] = typer.Option( ["World"], help="The name to say hi to.", autocompletion=complete_name - ) + ), ): for n in name: print(f"Hello {n}") diff --git a/docs_src/options_autocompletion/tutorial008.py b/docs_src/options_autocompletion/tutorial008.py index f90073b15f..118f4dd346 100644 --- a/docs_src/options_autocompletion/tutorial008.py +++ b/docs_src/options_autocompletion/tutorial008.py @@ -26,7 +26,7 @@ def complete_name(args: List[str], incomplete: str): def main( name: List[str] = typer.Option( ["World"], help="The name to say hi to.", autocompletion=complete_name - ) + ), ): for n in name: print(f"Hello {n}") diff --git a/docs_src/options_autocompletion/tutorial009.py b/docs_src/options_autocompletion/tutorial009.py index 829f209031..7e82c7ff07 100644 --- a/docs_src/options_autocompletion/tutorial009.py +++ b/docs_src/options_autocompletion/tutorial009.py @@ -27,7 +27,7 @@ def complete_name(ctx: typer.Context, args: List[str], incomplete: str): def main( name: List[str] = typer.Option( ["World"], help="The name to say hi to.", autocompletion=complete_name - ) + ), ): for n in name: print(f"Hello {n}") diff --git a/docs_src/parameter_types/datetime/tutorial002.py b/docs_src/parameter_types/datetime/tutorial002.py index ad21f7772d..4fbf91a250 100644 --- a/docs_src/parameter_types/datetime/tutorial002.py +++ b/docs_src/parameter_types/datetime/tutorial002.py @@ -6,7 +6,7 @@ def main( launch_date: datetime = typer.Argument( ..., formats=["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", "%m/%d/%Y"] - ) + ), ): print(f"Launch will be at: {launch_date}") diff --git a/docs_src/parameter_types/datetime/tutorial002_an.py b/docs_src/parameter_types/datetime/tutorial002_an.py index 6897432df1..661e783f40 100644 --- a/docs_src/parameter_types/datetime/tutorial002_an.py +++ b/docs_src/parameter_types/datetime/tutorial002_an.py @@ -10,7 +10,7 @@ def main( typer.Argument( formats=["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", "%m/%d/%Y"] ), - ] + ], ): print(f"Launch will be at: {launch_date}") diff --git a/docs_src/parameter_types/enum/tutorial002.py b/docs_src/parameter_types/enum/tutorial002.py index 545c579541..874971354a 100644 --- a/docs_src/parameter_types/enum/tutorial002.py +++ b/docs_src/parameter_types/enum/tutorial002.py @@ -10,7 +10,7 @@ class NeuralNetwork(str, Enum): def main( - network: NeuralNetwork = typer.Option(NeuralNetwork.simple, case_sensitive=False) + network: NeuralNetwork = typer.Option(NeuralNetwork.simple, case_sensitive=False), ): print(f"Training neural network of type: {network.value}") diff --git a/docs_src/parameter_types/enum/tutorial002_an.py b/docs_src/parameter_types/enum/tutorial002_an.py index 77c1057570..69ea5e146d 100644 --- a/docs_src/parameter_types/enum/tutorial002_an.py +++ b/docs_src/parameter_types/enum/tutorial002_an.py @@ -13,7 +13,7 @@ class NeuralNetwork(str, Enum): def main( network: Annotated[ NeuralNetwork, typer.Option(case_sensitive=False) - ] = NeuralNetwork.simple + ] = NeuralNetwork.simple, ): print(f"Training neural network of type: {network.value}") diff --git a/docs_src/parameter_types/path/tutorial002.py b/docs_src/parameter_types/path/tutorial002.py index b088655d6a..d9121bbc40 100644 --- a/docs_src/parameter_types/path/tutorial002.py +++ b/docs_src/parameter_types/path/tutorial002.py @@ -12,7 +12,7 @@ def main( writable=False, readable=True, resolve_path=True, - ) + ), ): text = config.read_text() print(f"Config file contents: {text}") diff --git a/docs_src/parameter_types/path/tutorial002_an.py b/docs_src/parameter_types/path/tutorial002_an.py index 052d3106dd..2cd0d07cf1 100644 --- a/docs_src/parameter_types/path/tutorial002_an.py +++ b/docs_src/parameter_types/path/tutorial002_an.py @@ -15,7 +15,7 @@ def main( readable=True, resolve_path=True, ), - ] + ], ): text = config.read_text() print(f"Config file contents: {text}") diff --git a/pyproject.toml b/pyproject.toml index 7e40e94256..44b71f3efd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,3 +74,53 @@ filterwarnings = [ # For pytest-xdist 'ignore::DeprecationWarning:xdist', ] + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade +] +ignore = [ + "E501", # line too long, handled by black + "B008", # do not perform function calls in argument defaults + "C901", # too complex + "W191", # indentation contains tabs +] + +[tool.ruff.lint.per-file-ignores] +# "__init__.py" = ["F401"] +# This file is more readable without yield from +"docs_src/progressbar/tutorial004.py" = ["UP028", "B007"] +# Default mutable data structure +"docs_src/options_autocompletion/tutorial006_an.py" = ["B006"] +"docs_src/multiple_values/multiple_options/tutorial002_an.py" = ["B006"] +"docs_src/options_autocompletion/tutorial007_an.py" = ["B006"] +"docs_src/options_autocompletion/tutorial008_an.py" = ["B006"] +"docs_src/options_autocompletion/tutorial009_an.py" = ["B006"] +"docs_src/parameter_types/enum/tutorial003_an.py" = ["B006"] +# Loop control variable `value` not used within loop body +"docs_src/progressbar/tutorial001.py" = ["B007"] +"docs_src/progressbar/tutorial003.py" = ["B007"] +"docs_src/progressbar/tutorial005.py" = ["B007"] +"docs_src/progressbar/tutorial006.py" = ["B007"] +# Local variable `delete` is assigned to but never used +"docs_src/prompt/tutorial003.py" = ["F841"] +# Loop control variable `x` not used within loop body +"docs_src/using_click/tutorial001.py" = ["B007"] + +# TODO: refactor _typing.py, remove unnecessary code +"typer/_typing.py" = ["UP036", "F822"] + +[tool.ruff.lint.isort] +known-third-party = ["typer", "click"] +# For docs_src/subcommands/tutorial003/ +known-first-party = ["reigns", "towns", "lands", "items", "users"] + +[tool.ruff.lint.pyupgrade] +# Preserve types, even if a file imports `from __future__ import annotations`. +keep-runtime-typing = true diff --git a/requirements-tests.txt b/requirements-tests.txt index e7850a4c06..74ba25fb41 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -6,5 +6,4 @@ coverage[toml] >=6.2,<7.0 pytest-xdist >=1.32.0,<4.0.0 pytest-sugar >=0.9.4,<0.10.0 mypy ==0.971 -black >=22.3.0,<23.0.0 -isort >=5.0.6,<6.0.0 +ruff ==0.2.0 diff --git a/scripts/format.sh b/scripts/format.sh index a01afd98c7..63b434e0b4 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -1,6 +1,6 @@ #!/bin/sh -e set -x +set -e -autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs_src typer tests --exclude=__init__.py -black typer tests docs_src -isort typer tests docs_src +ruff typer tests docs_src scripts --fix +ruff format typer tests docs_src scripts diff --git a/scripts/lint.sh b/scripts/lint.sh index f848ab1a0e..aa2c982271 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,5 +4,5 @@ set -e set -x mypy typer -black typer tests docs_src --check -isort typer tests docs_src --check-only +ruff typer tests docs_src scripts +ruff format typer tests --check diff --git a/tests/test_ambiguous_params.py b/tests/test_ambiguous_params.py index 7938ac57c8..4dbf09b569 100644 --- a/tests/test_ambiguous_params.py +++ b/tests/test_ambiguous_params.py @@ -35,10 +35,10 @@ def cmd(my_param: Annotated[str, typer.Argument("foo")]): with pytest.raises(AnnotatedParamWithDefaultValueError) as excinfo: runner.invoke(app) - assert vars(excinfo.value) == dict( - param_type=typer.models.ArgumentInfo, - argument_name="my_param", - ) + assert vars(excinfo.value) == { + "param_type": typer.models.ArgumentInfo, + "argument_name": "my_param", + } def test_allow_options_to_have_names(): @@ -70,24 +70,26 @@ def cmd(my_param: Annotated[str, param()] = param("foo")): with pytest.raises(MixedAnnotatedAndDefaultStyleError) as excinfo: runner.invoke(app) - assert vars(excinfo.value) == dict( - argument_name="my_param", - annotated_param_type=param_info_type, - default_param_type=param_info_type, - ) + assert vars(excinfo.value) == { + "argument_name": "my_param", + "annotated_param_type": param_info_type, + "default_param_type": param_info_type, + } def test_forbid_multiple_typer_params_in_annotated(): app = typer.Typer() @app.command() - def cmd(my_param: Annotated[str, typer.Argument(), typer.Argument()]): + def cmd( + my_param: Annotated[str, typer.Argument(), typer.Argument()], + ): ... # pragma: no cover with pytest.raises(MultipleTyperAnnotationsError) as excinfo: runner.invoke(app) - assert vars(excinfo.value) == dict(argument_name="my_param") + assert vars(excinfo.value) == {"argument_name": "my_param"} def test_allow_multiple_non_typer_params_in_annotated(): @@ -117,16 +119,18 @@ def make_string(): app = typer.Typer() @app.command() - def cmd(my_param: Annotated[str, param(default_factory=make_string)] = "hello"): + def cmd( + my_param: Annotated[str, param(default_factory=make_string)] = "hello", + ): ... # pragma: no cover with pytest.raises(DefaultFactoryAndDefaultValueError) as excinfo: runner.invoke(app) - assert vars(excinfo.value) == dict( - argument_name="my_param", - param_type=param_info_type, - ) + assert vars(excinfo.value) == { + "argument_name": "my_param", + "param_type": param_info_type, + } @pytest.mark.parametrize( @@ -165,16 +169,18 @@ def make_string(): app = typer.Typer() @app.command() - def cmd(my_param: str = param("hi", default_factory=make_string)): + def cmd( + my_param: str = param("hi", default_factory=make_string), + ): ... # pragma: no cover with pytest.raises(DefaultFactoryAndDefaultValueError) as excinfo: runner.invoke(app) - assert vars(excinfo.value) == dict( - argument_name="my_param", - param_type=param_info_type, - ) + assert vars(excinfo.value) == { + "argument_name": "my_param", + "param_type": param_info_type, + } @pytest.mark.parametrize( diff --git a/tests/test_compat/test_option_get_help.py b/tests/test_compat/test_option_get_help.py index c4966dc9b6..baca132cf0 100644 --- a/tests/test_compat/test_option_get_help.py +++ b/tests/test_compat/test_option_get_help.py @@ -42,8 +42,7 @@ def test_coverage_call(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_completion/test_completion.py b/tests/test_completion/test_completion.py index 7f36547707..ae5972a584 100644 --- a/tests/test_completion/test_completion.py +++ b/tests/test_completion/test_completion.py @@ -13,8 +13,7 @@ def test_show_completion(): "-c", f"{sys.executable} -m coverage run {mod.__file__} --show-completion", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "SHELL": "/bin/bash", "_TYPER_COMPLETE_TESTING": "True"}, ) @@ -32,8 +31,7 @@ def test_install_completion(): "-c", f"{sys.executable} -m coverage run {mod.__file__} --install-completion", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "SHELL": "/bin/bash", "_TYPER_COMPLETE_TESTING": "True"}, ) @@ -48,8 +46,7 @@ def test_install_completion(): def test_completion_invalid_instruction(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -64,8 +61,7 @@ def test_completion_invalid_instruction(): def test_completion_source_bash(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -82,8 +78,7 @@ def test_completion_source_bash(): def test_completion_source_invalid_shell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -97,8 +92,7 @@ def test_completion_source_invalid_shell(): def test_completion_source_invalid_instruction(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -112,8 +106,7 @@ def test_completion_source_invalid_instruction(): def test_completion_source_zsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -127,8 +120,7 @@ def test_completion_source_zsh(): def test_completion_source_fish(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -142,8 +134,7 @@ def test_completion_source_fish(): def test_completion_source_powershell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -160,8 +151,7 @@ def test_completion_source_powershell(): def test_completion_source_pwsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_completion/test_completion_complete.py b/tests/test_completion/test_completion_complete.py index e3fbb3154a..359768f859 100644 --- a/tests/test_completion/test_completion_complete.py +++ b/tests/test_completion/test_completion_complete.py @@ -8,8 +8,7 @@ def test_completion_complete_subcommand_bash(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -25,8 +24,7 @@ def test_completion_complete_subcommand_bash(): def test_completion_complete_subcommand_bash_invalid(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -42,8 +40,7 @@ def test_completion_complete_subcommand_bash_invalid(): def test_completion_complete_subcommand_zsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -61,8 +58,7 @@ def test_completion_complete_subcommand_zsh(): def test_completion_complete_subcommand_zsh_files(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -77,8 +73,7 @@ def test_completion_complete_subcommand_zsh_files(): def test_completion_complete_subcommand_fish(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -97,8 +92,7 @@ def test_completion_complete_subcommand_fish(): def test_completion_complete_subcommand_fish_should_complete(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -114,8 +108,7 @@ def test_completion_complete_subcommand_fish_should_complete(): def test_completion_complete_subcommand_fish_should_complete_no(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -131,8 +124,7 @@ def test_completion_complete_subcommand_fish_should_complete_no(): def test_completion_complete_subcommand_powershell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -149,8 +141,7 @@ def test_completion_complete_subcommand_powershell(): def test_completion_complete_subcommand_pwsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -167,8 +158,7 @@ def test_completion_complete_subcommand_pwsh(): def test_completion_complete_subcommand_noshell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_completion/test_completion_complete_no_help.py b/tests/test_completion/test_completion_complete_no_help.py index bf5762c06d..c67c77a82b 100644 --- a/tests/test_completion/test_completion_complete_no_help.py +++ b/tests/test_completion/test_completion_complete_no_help.py @@ -8,8 +8,7 @@ def test_completion_complete_subcommand_zsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -25,8 +24,7 @@ def test_completion_complete_subcommand_zsh(): def test_completion_complete_subcommand_fish(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -42,8 +40,7 @@ def test_completion_complete_subcommand_fish(): def test_completion_complete_subcommand_powershell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -58,8 +55,7 @@ def test_completion_complete_subcommand_powershell(): def test_completion_complete_subcommand_pwsh(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_completion/test_completion_install.py b/tests/test_completion/test_completion_install.py index 32c6f71dae..e823e388e4 100644 --- a/tests/test_completion/test_completion_install.py +++ b/tests/test_completion/test_completion_install.py @@ -18,8 +18,7 @@ def test_completion_install_no_shell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--install-completion"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -45,8 +44,7 @@ def test_completion_install_bash(): "--install-completion", "bash", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -88,8 +86,7 @@ def test_completion_install_zsh(): "--install-completion", "zsh", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -125,8 +122,7 @@ def test_completion_install_fish(): "--install-completion", "fish", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -148,7 +144,7 @@ def test_completion_install_fish(): def test_completion_install_powershell(): completion_path: Path = ( - Path.home() / f".config/powershell/Microsoft.PowerShell_profile.ps1" + Path.home() / ".config/powershell/Microsoft.PowerShell_profile.ps1" ) completion_path_bytes = f"{completion_path}\n".encode("windows-1252") text = "" diff --git a/tests/test_completion/test_completion_show.py b/tests/test_completion/test_completion_show.py index 196f27f048..5f94d50747 100644 --- a/tests/test_completion/test_completion_show.py +++ b/tests/test_completion/test_completion_show.py @@ -17,8 +17,7 @@ def test_completion_show_no_shell(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--show-completion"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -40,8 +39,7 @@ def test_completion_show_bash(): "--show-completion", "bash", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -66,8 +64,7 @@ def test_completion_source_zsh(): "--show-completion", "zsh", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -89,8 +86,7 @@ def test_completion_source_fish(): "--show-completion", "fish", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -112,8 +108,7 @@ def test_completion_source_powershell(): "--show-completion", "powershell", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -138,8 +133,7 @@ def test_completion_source_pwsh(): "--show-completion", "pwsh", ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_others.py b/tests/test_others.py index 3bc7fd7d72..12fa0ae09b 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -145,8 +145,7 @@ def test_completion_untyped_parameters(): file_path = Path(__file__).parent / "assets/completion_no_types.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -163,8 +162,7 @@ def test_completion_untyped_parameters(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Hello World" in result.stdout @@ -174,8 +172,7 @@ def test_completion_untyped_parameters_different_order_correct_names(): file_path = Path(__file__).parent / "assets/completion_no_types_order.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -192,8 +189,7 @@ def test_completion_untyped_parameters_different_order_correct_names(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Hello World" in result.stdout @@ -236,7 +232,7 @@ def main(arg1, arg2: int, arg3: "int", arg4: bool = False, arg5: "bool" = False) def test_context_settings_inheritance_single_command(): - app = typer.Typer(context_settings=dict(help_option_names=["-h", "--help"])) + app = typer.Typer(context_settings={"help_option_names": ["-h", "--help"]}) @app.command() def main(name: str): diff --git a/tests/test_prog_name.py b/tests/test_prog_name.py index 58626c7ac2..cfb5a3464f 100644 --- a/tests/test_prog_name.py +++ b/tests/test_prog_name.py @@ -7,8 +7,7 @@ def test_custom_prog_name(): file_path = Path(__file__).parent / "assets/prog_name.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path), "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage: custom-name [OPTIONS] I" in result.stdout diff --git a/tests/test_tracebacks.py b/tests/test_tracebacks.py index 639f36e53f..8c8ab0295d 100644 --- a/tests/test_tracebacks.py +++ b/tests/test_tracebacks.py @@ -8,8 +8,7 @@ def test_traceback_no_rich(): file_path = Path(__file__).parent / "assets/type_error_no_rich.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -24,8 +23,7 @@ def test_traceback_no_rich_short_disable(): file_path = Path(__file__).parent / "assets/type_error_no_rich_short_disable.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -40,8 +38,7 @@ def test_unmodified_traceback(): file_path = Path(__file__).parent / "assets/type_error_normal_traceback.py" result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py index 00e5734463..cb1836bfd3 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py @@ -35,8 +35,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial001_an.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial001_an.py index b1d5655366..1db27f81a5 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial001_an.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial001_an.py @@ -35,8 +35,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py index 11b096b6c2..9750a6dc7f 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py @@ -22,7 +22,7 @@ def test_help(): def test_call_no_arg(): greetings = ["Hello Deadpool", "Hello Rick", "Hello Morty", "Hello Hiro"] - for i in range(3): + for _i in range(3): result = runner.invoke(app) assert result.exit_code == 0 assert any(greet in result.output for greet in greetings) @@ -37,8 +37,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial002_an.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial002_an.py index 4bf1332d9c..cf818bde8f 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial002_an.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial002_an.py @@ -22,7 +22,7 @@ def test_help(): def test_call_no_arg(): greetings = ["Hello Deadpool", "Hello Rick", "Hello Morty", "Hello Hiro"] - for i in range(3): + for _i in range(3): result = runner.invoke(app) assert result.exit_code == 0 assert any(greet in result.output for greet in greetings) @@ -37,8 +37,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py index 1567e12565..196bdb77bc 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py @@ -55,8 +55,7 @@ def test_call_env_var_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001_an.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001_an.py index 90a5df9f96..73379b6207 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001_an.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001_an.py @@ -55,8 +55,7 @@ def test_call_env_var_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py index ce960f4c0c..b34a601a0b 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py @@ -42,8 +42,7 @@ def test_call_env_var2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002_an.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002_an.py index a62d4e0df2..e8768ff2a3 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002_an.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002_an.py @@ -42,8 +42,7 @@ def test_call_env_var2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py index 396ebf23a5..74928cb3a5 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py @@ -42,8 +42,7 @@ def test_call_env_var_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003_an.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003_an.py index c1cc2bc8a8..01cc303c20 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003_an.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003_an.py @@ -42,8 +42,7 @@ def test_call_env_var_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py index 1822f62a92..1bc7b8d2dd 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py @@ -45,8 +45,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial001_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial001_an.py index 7ca0bf7ce6..9b4c2efa86 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial001_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial001_an.py @@ -45,8 +45,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py index 30a183e1a2..78c8cd2d11 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial002_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial002_an.py index 5473708509..f1ad669abc 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial002_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial002_an.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py index 9a1b8d1666..df486cf199 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial003_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial003_an.py index 7be39e0b95..e0d09f881f 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial003_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial003_an.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py index 771fbaf6dc..805753e08e 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial004_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial004_an.py index 0c87e811b5..c2613a4285 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial004_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial004_an.py @@ -32,8 +32,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py index cf962bb4fe..64c99a5271 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial005_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial005_an.py index 908e8f1d1d..28d8ee57b9 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial005_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial005_an.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py index 1b4229edb6..4c8abb8a86 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial006_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial006_an.py index 64a985d26d..e60ec51666 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial006_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial006_an.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py index 3c6eddd028..56b38254e4 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial007_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial007_an.py index fae243df06..9be2f57831 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial007_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial007_an.py @@ -30,8 +30,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py index f26c6e75ab..14d9105454 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py @@ -43,8 +43,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008_an.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008_an.py index 66316d2b11..58f06bdd12 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008_an.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008_an.py @@ -43,8 +43,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py index efcf8a11f6..46be46cbbd 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py @@ -44,8 +44,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001_an.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001_an.py index d1ad8ebde4..45d680b6a3 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001_an.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001_an.py @@ -44,8 +44,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py index c616d467ee..ed04c26e19 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py @@ -33,8 +33,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002_an.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002_an.py index 5a0a768976..0696b6b386 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002_an.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002_an.py @@ -33,8 +33,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py index b484ad2266..0d0ad50551 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py @@ -44,8 +44,7 @@ def test_call_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py b/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py index f5156699b1..fd5abae1ef 100644 --- a/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py @@ -37,8 +37,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py index 68bcdf1fd0..b2ec90bc6a 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py @@ -69,8 +69,7 @@ def test_wrong_verbose(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial002.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial002.py index d8478d35eb..e19ca9d22b 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial002.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial002.py @@ -20,8 +20,7 @@ def test_app(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial003.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial003.py index bf0e5f3c50..163341f67e 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial003.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial003.py @@ -25,8 +25,7 @@ def test_for_coverage(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial004.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial004.py index 79432286ce..23179d66b7 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial004.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial004.py @@ -27,8 +27,7 @@ def test_app(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_context/test_tutorial001.py b/tests/test_tutorial/test_commands/test_context/test_tutorial001.py index 2e3c7b784c..be6c0dce43 100644 --- a/tests/test_tutorial/test_commands/test_context/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_context/test_tutorial001.py @@ -27,8 +27,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_context/test_tutorial002.py b/tests/test_tutorial/test_commands/test_context/test_tutorial002.py index 6aab364c2a..a83f81a80c 100644 --- a/tests/test_tutorial/test_commands/test_context/test_tutorial002.py +++ b/tests/test_tutorial/test_commands/test_context/test_tutorial002.py @@ -33,8 +33,7 @@ def test_callback(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_context/test_tutorial003.py b/tests/test_tutorial/test_commands/test_context/test_tutorial003.py index 6d5b5c37fb..1ec8f54649 100644 --- a/tests/test_tutorial/test_commands/test_context/test_tutorial003.py +++ b/tests/test_tutorial/test_commands/test_context/test_tutorial003.py @@ -33,8 +33,7 @@ def test_callback(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_context/test_tutorial004.py b/tests/test_tutorial/test_commands/test_context/test_tutorial004.py index 8ce5997107..ade78ad252 100644 --- a/tests/test_tutorial/test_commands/test_context/test_tutorial004.py +++ b/tests/test_tutorial/test_commands/test_context/test_tutorial004.py @@ -22,8 +22,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py index e2c99e35c4..91f0fb615b 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py @@ -103,8 +103,7 @@ def test_init(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py b/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py index e349718463..0a8667e133 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial001_an.py @@ -103,8 +103,7 @@ def test_init(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial002.py b/tests/test_tutorial/test_commands/test_help/test_tutorial002.py index f53b5fe6f6..447012dcc4 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial002.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial002.py @@ -50,8 +50,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial003.py b/tests/test_tutorial/test_commands/test_help/test_tutorial003.py index 7d5f47fa62..d4e423a03e 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial003.py @@ -38,8 +38,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial004.py b/tests/test_tutorial/test_commands/test_help/test_tutorial004.py index 1b0ec591b2..20127fc6b3 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial004.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial004.py @@ -53,8 +53,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial004_an.py b/tests/test_tutorial/test_commands/test_help/test_tutorial004_an.py index a7481667f4..f445f89c6e 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial004_an.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial004_an.py @@ -53,8 +53,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial005.py b/tests/test_tutorial/test_commands/test_help/test_tutorial005.py index f3b160eb99..2cf6de837e 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial005.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial005.py @@ -54,8 +54,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial005_an.py b/tests/test_tutorial/test_commands/test_help/test_tutorial005_an.py index 91af901bb6..002caf4459 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial005_an.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial005_an.py @@ -54,8 +54,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial006.py b/tests/test_tutorial/test_commands/test_help/test_tutorial006.py index 14f0815b3b..d9da8331cb 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial006.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial006.py @@ -45,8 +45,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial007.py b/tests/test_tutorial/test_commands/test_help/test_tutorial007.py index 3a753040f8..1f320d7f3c 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial007.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial007.py @@ -49,8 +49,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial007_an.py b/tests/test_tutorial/test_commands/test_help/test_tutorial007_an.py index 98c748a36a..2acb91367c 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial007_an.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial007_an.py @@ -49,8 +49,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial008.py b/tests/test_tutorial/test_commands/test_help/test_tutorial008.py index b460d9c011..299a4afb58 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial008.py @@ -26,8 +26,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_index/test_tutorial001.py b/tests/test_tutorial/test_commands/test_index/test_tutorial001.py index fee5e76e19..4c978e0ae5 100644 --- a/tests/test_tutorial/test_commands/test_index/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_index/test_tutorial001.py @@ -25,8 +25,7 @@ def test_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_index/test_tutorial002.py b/tests/test_tutorial/test_commands/test_index/test_tutorial002.py index b49e38be0f..fd10fe0204 100644 --- a/tests/test_tutorial/test_commands/test_index/test_tutorial002.py +++ b/tests/test_tutorial/test_commands/test_index/test_tutorial002.py @@ -34,8 +34,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_index/test_tutorial003.py b/tests/test_tutorial/test_commands/test_index/test_tutorial003.py index 89651f9343..8855d3ba53 100644 --- a/tests/test_tutorial/test_commands/test_index/test_tutorial003.py +++ b/tests/test_tutorial/test_commands/test_index/test_tutorial003.py @@ -34,8 +34,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_name/test_tutorial001.py b/tests/test_tutorial/test_commands/test_name/test_tutorial001.py index 0dae24f2ed..03ac8f205e 100644 --- a/tests/test_tutorial/test_commands/test_name/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_name/test_tutorial001.py @@ -33,8 +33,7 @@ def test_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial001.py b/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial001.py index 5e76dd90cb..09decc74a2 100644 --- a/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial001.py @@ -26,8 +26,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial002.py b/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial002.py index 8af2daffb3..e3b2b013d8 100644 --- a/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial002.py +++ b/tests/test_tutorial/test_commands/test_one_or_multiple/test_tutorial002.py @@ -28,8 +28,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_options/test_tutorial001.py b/tests/test_tutorial/test_commands/test_options/test_tutorial001.py index f15e76bb5f..955447f156 100644 --- a/tests/test_tutorial/test_commands/test_options/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_options/test_tutorial001.py @@ -70,8 +70,7 @@ def test_init(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py b/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py index 9dd919c0f4..51c6edfc03 100644 --- a/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py +++ b/tests/test_tutorial/test_commands/test_options/test_tutorial001_an.py @@ -70,8 +70,7 @@ def test_init(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_exceptions/test_tutorial001.py b/tests/test_tutorial/test_exceptions/test_tutorial001.py index 483f4340bb..26b6ca943c 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial001.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial001.py @@ -14,8 +14,7 @@ def test_traceback_rich(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -31,8 +30,7 @@ def test_standard_traceback_env_var(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": "1"}, ) @@ -47,8 +45,7 @@ def test_standard_traceback_env_var(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_exceptions/test_tutorial002.py b/tests/test_tutorial/test_exceptions/test_tutorial002.py index f65cfd6f58..0bcf3671f8 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial002.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial002.py @@ -14,8 +14,7 @@ def test_traceback_rich(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path), "secret"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -31,8 +30,7 @@ def test_standard_traceback_env_var(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path), "secret"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": "1"}, ) @@ -47,8 +45,7 @@ def test_standard_traceback_env_var(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_exceptions/test_tutorial003.py b/tests/test_tutorial/test_exceptions/test_tutorial003.py index 3da786d24d..2c3ed634cd 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial003.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial003.py @@ -14,8 +14,7 @@ def test_traceback_rich_pretty_short_disable(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -30,8 +29,7 @@ def test_traceback_rich_pretty_short_disable(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_exceptions/test_tutorial004.py b/tests/test_tutorial/test_exceptions/test_tutorial004.py index 417e0d4608..c48c4bad61 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial004.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial004.py @@ -14,8 +14,7 @@ def test_rich_pretty_exceptions_disable(): file_path = Path(mod.__file__) result = subprocess.run( [sys.executable, "-m", "coverage", "run", str(file_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, ) @@ -29,8 +28,7 @@ def test_rich_pretty_exceptions_disable(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001.py b/tests/test_tutorial/test_first_steps/test_tutorial001.py index 4a465dbe41..9392282297 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial001.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial001.py @@ -19,8 +19,7 @@ def test_cli(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial002.py b/tests/test_tutorial/test_first_steps/test_tutorial002.py index 7192545c65..766819b51f 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial002.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial002.py @@ -27,8 +27,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial003.py b/tests/test_tutorial/test_first_steps/test_tutorial003.py index 6c39d849b5..d29c798506 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial003.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial003.py @@ -27,8 +27,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial004.py b/tests/test_tutorial/test_first_steps/test_tutorial004.py index c419bb9014..d7f259fbeb 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial004.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial004.py @@ -51,8 +51,7 @@ def test_formal_3(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial005.py b/tests/test_tutorial/test_first_steps/test_tutorial005.py index 816ab0c413..6098bd00be 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial005.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial005.py @@ -51,8 +51,7 @@ def test_formal_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_first_steps/test_tutorial006.py b/tests/test_tutorial/test_first_steps/test_tutorial006.py index 08cafe7ff3..2234c47f63 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial006.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial006.py @@ -46,8 +46,7 @@ def test_formal_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial001.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial001.py index 315000bd66..4241130c1f 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial001.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial001.py @@ -21,8 +21,7 @@ def test_main(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py index ad323c3681..4a1c93f1cd 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py @@ -44,8 +44,7 @@ def test_valid_args(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py index e420acb46d..b634c08ef3 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002_an.py @@ -46,8 +46,7 @@ def test_valid_args(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py index 4293ed8d3d..0086df3b80 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py @@ -38,8 +38,7 @@ def test_3_user(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py index 20ea235307..fa2ae4497c 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py @@ -38,8 +38,7 @@ def test_3_user(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002.py index d30357e765..79aaaaef81 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002.py @@ -32,8 +32,7 @@ def test_2_number(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002_an.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002_an.py index 92fb291cdb..c52f9352a4 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002_an.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial002_an.py @@ -32,8 +32,7 @@ def test_2_number(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py index 013b19f873..c225665e6b 100644 --- a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py +++ b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001.py @@ -41,8 +41,7 @@ def test_invalid_user(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py index de8cfa9f20..44ae98c786 100644 --- a/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py +++ b/tests/test_tutorial/test_multiple_values/test_options_with_multiple_values/test_tutorial001_an.py @@ -41,8 +41,7 @@ def test_invalid_user(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial001.py b/tests/test_tutorial/test_options/test_callback/test_tutorial001.py index f5a43d0fbb..5c2c19ed77 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial001.py @@ -27,8 +27,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_callback/test_tutorial001_an.py index 7d5cda20cc..5bbe0b08a0 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial001_an.py @@ -27,8 +27,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial003.py b/tests/test_tutorial/test_options/test_callback/test_tutorial003.py index 7726997ff0..fe2ebd9d08 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial003.py @@ -29,8 +29,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -39,8 +38,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py index 7bb3754816..cb2715f02e 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py @@ -29,8 +29,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -39,8 +38,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial004.py b/tests/test_tutorial/test_options/test_callback/test_tutorial004.py index 473cd9d62f..68b74448f7 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial004.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial004.py @@ -29,8 +29,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -39,8 +38,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py b/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py index 34810f8eef..b410fa7044 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py @@ -29,8 +29,7 @@ def test_2(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -39,8 +38,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial001.py b/tests/test_tutorial/test_options/test_help/test_tutorial001.py index 3e89d55290..bc4d01fb36 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial001.py @@ -42,8 +42,7 @@ def test_formal(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_help/test_tutorial001_an.py index 99d3279aac..a1ea0be4a1 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial001_an.py @@ -42,8 +42,7 @@ def test_formal(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial002.py b/tests/test_tutorial/test_options/test_help/test_tutorial002.py index 260d6453e8..37c5b72617 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial002.py @@ -38,8 +38,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial002_an.py b/tests/test_tutorial/test_options/test_help/test_tutorial002_an.py index 7d61a41dd8..a8364b017a 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial002_an.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial002_an.py @@ -38,8 +38,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial003.py b/tests/test_tutorial/test_options/test_help/test_tutorial003.py index f6a9826e9b..b7b2af2b46 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial003.py @@ -29,8 +29,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_help/test_tutorial003_an.py index 88e71ab473..948d566308 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial003_an.py @@ -29,8 +29,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial001.py b/tests/test_tutorial/test_options/test_name/test_tutorial001.py index da14c934c1..21c6729ad0 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial001.py @@ -35,8 +35,7 @@ def test_call_no_args(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py index c5c57b2ee8..6beffcb645 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial001_an.py @@ -35,8 +35,7 @@ def test_call_no_args(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial002.py b/tests/test_tutorial/test_options/test_name/test_tutorial002.py index 5d50e67d1c..0b4b8ced41 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial002.py @@ -36,8 +36,7 @@ def test_call_long(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial002_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial002_an.py index b77c3bcc29..7a3742bf62 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial002_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial002_an.py @@ -36,8 +36,7 @@ def test_call_long(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial003.py b/tests/test_tutorial/test_options/test_name/test_tutorial003.py index 729470985a..80bd7f2da2 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial003.py @@ -30,8 +30,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial003_an.py index cf097e2388..eb15ad2a6b 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial003_an.py @@ -30,8 +30,7 @@ def test_call(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial004.py b/tests/test_tutorial/test_options/test_name/test_tutorial004.py index b0f4b5c612..93253ac5e5 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial004.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial004.py @@ -36,8 +36,7 @@ def test_call_long(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial004_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial004_an.py index 087b436d55..f3cc9d958d 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial004_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial004_an.py @@ -36,8 +36,7 @@ def test_call_long(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial005.py b/tests/test_tutorial/test_options/test_name/test_tutorial005.py index 440c036a09..fa70682bc8 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial005.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial005.py @@ -48,8 +48,7 @@ def test_call_condensed_wrong_order(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial005_an.py b/tests/test_tutorial/test_options/test_name/test_tutorial005_an.py index 5ca123f0bd..0a947f7a41 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial005_an.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial005_an.py @@ -48,8 +48,7 @@ def test_call_condensed_wrong_order(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py index 588bc97149..3ac3deff57 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py @@ -36,8 +36,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial001_an.py index eb2333c9f6..0592d34db8 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial001_an.py @@ -36,8 +36,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py index fd2048fd25..b037ddb518 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py @@ -36,8 +36,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial002_an.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial002_an.py index 5d81c6d8d1..fa59426ed3 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial002_an.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial002_an.py @@ -36,8 +36,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py index 2684bcedc9..210e5afa5c 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py @@ -45,8 +45,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py index b163386438..5d1c0865da 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial003_an.py @@ -45,8 +45,7 @@ def test_help(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_required/test_tutorial001.py b/tests/test_tutorial/test_options/test_required/test_tutorial001.py index 2e14a9f73e..c4c84ce451 100644 --- a/tests/test_tutorial/test_options/test_required/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_required/test_tutorial001.py @@ -47,8 +47,7 @@ def test_help_no_rich(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_required/test_tutorial001_an.py b/tests/test_tutorial/test_options/test_required/test_tutorial001_an.py index 48d82cf331..259609f0de 100644 --- a/tests/test_tutorial/test_options/test_required/test_tutorial001_an.py +++ b/tests/test_tutorial/test_options/test_required/test_tutorial001_an.py @@ -47,8 +47,7 @@ def test_help_no_rich(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options/test_version/test_tutorial003.py b/tests/test_tutorial/test_options/test_version/test_tutorial003.py index a5a706077c..4287a5db0c 100644 --- a/tests/test_tutorial/test_options/test_version/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_version/test_tutorial003.py @@ -34,8 +34,7 @@ def test_3(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -44,8 +43,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py index 75b024af52..3081cb440f 100644 --- a/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py @@ -34,8 +34,7 @@ def test_3(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout @@ -44,8 +43,7 @@ def test_script(): def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py index 3dc81a7624..49af214900 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py index e23af20fb3..94f32fb21a 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py index e0665232ed..5870e445c3 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py index b8e04cb8e3..6583f9dccf 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py index 1aaec9d4ec..1d7784ad2b 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py index cb951c75a4..30196732c6 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -36,8 +35,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py index 9af6681eb1..bfa2aedb8a 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -37,8 +36,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py index a015f6af9e..6c8c294886 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -37,8 +36,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py index 982c7d94c0..a347237e71 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -38,8 +37,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py index 8c662543ea..ff5c25987c 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -38,8 +37,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py index 999240d970..8d9a73e755 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -38,8 +37,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py index b56523bcbb..fd4b65f1f1 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py @@ -12,8 +12,7 @@ def test_completion(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, " "], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env={ **os.environ, @@ -38,8 +37,7 @@ def test_1(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py index 356a99284b..61f0f2597c 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001.py @@ -40,8 +40,7 @@ def test_invalid_no_force(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py index ef92385022..b549583e23 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial001_an.py @@ -40,8 +40,7 @@ def test_invalid_no_force(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py index 413ccd4f67..5b537e4314 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py @@ -59,8 +59,7 @@ def test_invalid_no_accept(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py index 0498c3299f..9444596c30 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002_an.py @@ -59,8 +59,7 @@ def test_invalid_no_accept(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003.py index 83226bd87c..794efece57 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003.py @@ -36,8 +36,7 @@ def test_no_force(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003_an.py index c1f09c411b..ef608dd9e8 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial003_an.py @@ -36,8 +36,7 @@ def test_no_force(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004.py index a01034d6eb..6b891544c6 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004.py @@ -40,8 +40,7 @@ def test_short_demo(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004_an.py index b4d1edeacd..e607310087 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial004_an.py @@ -40,8 +40,7 @@ def test_short_demo(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001.py index e6a8be69ed..6e21535fa6 100644 --- a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001.py @@ -32,8 +32,7 @@ def test_parse_custom_type_with_default(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001_an.py index 779d86fbf5..7b52d5e1d1 100644 --- a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial001_an.py @@ -32,8 +32,7 @@ def test_parse_custom_type_with_default(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002.py index f9e7da08cf..fc72db408a 100644 --- a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002.py @@ -32,8 +32,7 @@ def test_parse_custom_type_with_default(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002_an.py index fe3ce78847..c31d69ae74 100644 --- a/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_custom_types/test_tutorial002_an.py @@ -32,8 +32,7 @@ def test_parse_custom_type_with_default(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py index 215e5deb8a..030bc41396 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py @@ -41,8 +41,7 @@ def test_invalid(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002.py index ec8fc71cd1..0c08f1b046 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002.py @@ -27,8 +27,7 @@ def test_usa_weird_date_format(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002_an.py index ebae67a0ef..d89821bf7f 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial002_an.py @@ -27,8 +27,7 @@ def test_usa_weird_date_format(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout 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 3dc997a2d2..67cf7b915a 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 @@ -47,8 +47,7 @@ def test_invalid_other(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout 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 293a1760bf..6c712d3b6e 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 @@ -27,8 +27,7 @@ def test_mix(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002_an.py index c60013daa9..a3c72b7eea 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial002_an.py @@ -27,8 +27,7 @@ def test_mix(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout 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 813bf997ae..98c882ebc1 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 @@ -41,8 +41,7 @@ def test_call_multiple_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003_an.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003_an.py index b0bc874e02..46dd4018a5 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003_an.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003_an.py @@ -41,8 +41,7 @@ def test_call_multiple_arg(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001.py index 061266abc8..24259b1e7e 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001.py @@ -26,8 +26,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001_an.py index 78b4893072..4be35a88a4 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial001_an.py @@ -26,8 +26,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py index bbb7696634..5b6549b380 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py @@ -28,8 +28,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py index 8f4550fbb7..fcddf8f6c2 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py @@ -28,8 +28,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003.py index ae452d0ddd..5dda6d3cb8 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003.py @@ -25,8 +25,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003_an.py index 5dc083133b..4b48675ade 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial003_an.py @@ -25,8 +25,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py index aa51f39e18..6821a5e1b8 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py @@ -29,8 +29,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py index 2808609a95..f56d8c6f93 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py @@ -29,8 +29,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py index 7f79fd42c0..8c1b3b7fff 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py @@ -31,8 +31,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py index 1fff5875e8..bd39911425 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py @@ -31,8 +31,7 @@ def test_main(tmpdir): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py index b232dba532..e7ac0a1d4f 100644 --- a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py @@ -41,8 +41,7 @@ def test_invalid(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index efec0467b9..7269255a9b 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -76,8 +76,7 @@ def test_negative_score(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py index 6bc60beeb2..6e354f77ae 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001_an.py @@ -76,8 +76,7 @@ def test_negative_score(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py index 2bc0e23e17..da8d1c1a6e 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002.py @@ -31,8 +31,7 @@ def test_clamped(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py index de1eaa982f..db1a73569f 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial002_an.py @@ -31,8 +31,7 @@ def test_clamped(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003.py index 3d0a741cf7..a639447c98 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003.py @@ -51,8 +51,7 @@ def test_verbose_short_3_condensed(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003_an.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003_an.py index 4e2a0c7190..71498a9731 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003_an.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial003_an.py @@ -51,8 +51,7 @@ def test_verbose_short_3_condensed(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py index a616d8f141..4ad4d2ead5 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py @@ -48,8 +48,7 @@ def test_dir(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py index efa6097c2f..7c4699186d 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py @@ -48,8 +48,7 @@ def test_dir(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py index 97c7b7fdb3..069c24a910 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py @@ -41,8 +41,7 @@ def test_dir(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py index ae93fae160..54d79ccaf8 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py @@ -41,8 +41,7 @@ def test_dir(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py index 0f60bc544d..aa9503e908 100644 --- a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py @@ -31,8 +31,7 @@ def test_invalid_uuid(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_prompt/test_tutorial001.py b/tests/test_tutorial/test_prompt/test_tutorial001.py index 00c9061d19..4b01d6d42d 100644 --- a/tests/test_tutorial/test_prompt/test_tutorial001.py +++ b/tests/test_tutorial/test_prompt/test_tutorial001.py @@ -22,8 +22,7 @@ def test_cli(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_prompt/test_tutorial002.py b/tests/test_tutorial/test_prompt/test_tutorial002.py index 1d3aa911c8..9ed3c2d152 100644 --- a/tests/test_tutorial/test_prompt/test_tutorial002.py +++ b/tests/test_tutorial/test_prompt/test_tutorial002.py @@ -30,8 +30,7 @@ def test_no_confirm(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_prompt/test_tutorial003.py b/tests/test_tutorial/test_prompt/test_tutorial003.py index b34d82301d..962ceca6ef 100644 --- a/tests/test_tutorial/test_prompt/test_tutorial003.py +++ b/tests/test_tutorial/test_prompt/test_tutorial003.py @@ -29,8 +29,7 @@ def test_no_confirm(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial001.py b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial001.py index f4bdf5ef96..ec76dfebf1 100644 --- a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial001.py +++ b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial001.py @@ -20,8 +20,7 @@ def test_cli(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial002.py b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial002.py index 301142d1e0..bfe8c35278 100644 --- a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial002.py +++ b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial002.py @@ -20,8 +20,7 @@ def test_cli(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial003.py b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial003.py index 7ac342db55..eb289a1443 100644 --- a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial003.py +++ b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial003.py @@ -25,8 +25,7 @@ def test_for_coverage(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial004.py b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial004.py index e2d23d0b4d..f22b77f916 100644 --- a/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial004.py +++ b/tests/test_tutorial/test_subcommands/test_callback_override/test_tutorial004.py @@ -27,8 +27,7 @@ def test_for_coverage(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial001.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial001.py index dfdb9f444a..fad028d416 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial001.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial001.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial002.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial002.py index dc81bd941d..d65b60a287 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial002.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial002.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial003.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial003.py index af60a9ea44..0b64a47954 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial003.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial003.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial004.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial004.py index 75e3ce40f0..667ce75a4a 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial004.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial004.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial005.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial005.py index 5b5697473e..815af7c126 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial005.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial005.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial006.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial006.py index 4b0b9166e1..cf2117965e 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial006.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial006.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial007.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial007.py index faffc70083..3935dee2da 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial007.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial007.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial008.py b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial008.py index 6a4d238d32..17f0826ca8 100644 --- a/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial008.py +++ b/tests/test_tutorial/test_subcommands/test_name_help/test_tutorial008.py @@ -33,8 +33,7 @@ def test_command(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_tutorial001.py b/tests/test_tutorial/test_subcommands/test_tutorial001.py index 1280e22f5a..6b228bd788 100644 --- a/tests/test_tutorial/test_subcommands/test_tutorial001.py +++ b/tests/test_tutorial/test_subcommands/test_tutorial001.py @@ -12,7 +12,7 @@ @pytest.fixture() def mod(monkeypatch): - with monkeypatch.context() as m: + with monkeypatch.context(): monkeypatch.syspath_prepend(list(tutorial001.__path__)[0]) from docs_src.subcommands.tutorial001 import main @@ -92,8 +92,7 @@ def test_scripts(mod): for module in [mod, items, users]: result = subprocess.run( [sys.executable, "-m", "coverage", "run", module.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env=env, ) diff --git a/tests/test_tutorial/test_subcommands/test_tutorial002.py b/tests/test_tutorial/test_subcommands/test_tutorial002.py index 3e1607d838..2b86bb3730 100644 --- a/tests/test_tutorial/test_subcommands/test_tutorial002.py +++ b/tests/test_tutorial/test_subcommands/test_tutorial002.py @@ -71,8 +71,7 @@ def test_users_delete(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_subcommands/test_tutorial003.py b/tests/test_tutorial/test_subcommands/test_tutorial003.py index 2d6149cf6a..d109cb47d1 100644 --- a/tests/test_tutorial/test_subcommands/test_tutorial003.py +++ b/tests/test_tutorial/test_subcommands/test_tutorial003.py @@ -165,8 +165,7 @@ def test_scripts(mod): for module in [mod, items, lands, reigns, towns, users]: result = subprocess.run( [sys.executable, "-m", "coverage", "run", module.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", env=env, ) diff --git a/tests/test_tutorial/test_terminating/test_tutorial001.py b/tests/test_tutorial/test_terminating/test_tutorial001.py index f6651eb057..6306fc2e15 100644 --- a/tests/test_tutorial/test_terminating/test_tutorial001.py +++ b/tests/test_tutorial/test_terminating/test_tutorial001.py @@ -37,8 +37,7 @@ def test_existing_no_standalone(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_terminating/test_tutorial002.py b/tests/test_tutorial/test_terminating/test_tutorial002.py index 8c599fe976..89f13bac8b 100644 --- a/tests/test_tutorial/test_terminating/test_tutorial002.py +++ b/tests/test_tutorial/test_terminating/test_tutorial002.py @@ -27,8 +27,7 @@ def test_root(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_terminating/test_tutorial003.py b/tests/test_tutorial/test_terminating/test_tutorial003.py index 7a1909a871..8fc5f68de4 100644 --- a/tests/test_tutorial/test_terminating/test_tutorial003.py +++ b/tests/test_tutorial/test_terminating/test_tutorial003.py @@ -46,8 +46,7 @@ def test_root_no_rich(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_testing/test_app01.py b/tests/test_tutorial/test_testing/test_app01.py index 773941a728..89acf56280 100644 --- a/tests/test_tutorial/test_testing/test_app01.py +++ b/tests/test_tutorial/test_testing/test_app01.py @@ -12,8 +12,7 @@ def test_app01(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_testing/test_app02.py b/tests/test_tutorial/test_testing/test_app02.py index 8c29d38bfa..e95e13ca5c 100644 --- a/tests/test_tutorial/test_testing/test_app02.py +++ b/tests/test_tutorial/test_testing/test_app02.py @@ -12,8 +12,7 @@ def test_app02(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_testing/test_app02_an.py b/tests/test_tutorial/test_testing/test_app02_an.py index 140a7e37ca..89764d6316 100644 --- a/tests/test_tutorial/test_testing/test_app02_an.py +++ b/tests/test_tutorial/test_testing/test_app02_an.py @@ -12,8 +12,7 @@ def test_app02_an(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_testing/test_app03.py b/tests/test_tutorial/test_testing/test_app03.py index aea281dea1..3f65d47806 100644 --- a/tests/test_tutorial/test_testing/test_app03.py +++ b/tests/test_tutorial/test_testing/test_app03.py @@ -12,8 +12,7 @@ def test_app03(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_using_click/test_tutorial003.py b/tests/test_tutorial/test_using_click/test_tutorial003.py index 55f7f16f9e..1dd26a7e04 100644 --- a/tests/test_tutorial/test_using_click/test_tutorial003.py +++ b/tests/test_tutorial/test_using_click/test_tutorial003.py @@ -34,8 +34,7 @@ def test_click(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_tutorial/test_using_click/test_tutorial004.py b/tests/test_tutorial/test_using_click/test_tutorial004.py index 06078d7e50..72800aec60 100644 --- a/tests/test_tutorial/test_using_click/test_tutorial004.py +++ b/tests/test_tutorial/test_using_click/test_tutorial004.py @@ -33,8 +33,7 @@ def test_click_dropdb(): def test_script(): result = subprocess.run( [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, encoding="utf-8", ) assert "Usage" in result.stdout diff --git a/tests/test_type_conversion.py b/tests/test_type_conversion.py index a4102daadc..21ad57436c 100644 --- a/tests/test_type_conversion.py +++ b/tests/test_type_conversion.py @@ -98,7 +98,7 @@ def test_custom_parse(): @app.command() def custom_parser( - hex_value: int = typer.Argument(None, parser=lambda x: int(x, 0)) + hex_value: int = typer.Argument(None, parser=lambda x: int(x, 0)), ): assert hex_value == 0x56 @@ -122,7 +122,7 @@ def convert( @app.command() def custom_click_type( - hex_value: int = typer.Argument(None, click_type=BaseNumberParamType()) + hex_value: int = typer.Argument(None, click_type=BaseNumberParamType()), ): assert hex_value == 0x56 diff --git a/typer/_completion_shared.py b/typer/_completion_shared.py index 3202e18ed8..1fb82e8406 100644 --- a/typer/_completion_shared.py +++ b/typer/_completion_shared.py @@ -87,11 +87,11 @@ def get_completion_script(*, prog_name: str, complete_var: str, shell: str) -> s raise click.exceptions.Exit(1) return ( script - % dict( - complete_func="_{}_completion".format(cf_name), - prog_name=prog_name, - autocomplete_var=complete_var, - ) + % { + "complete_func": f"_{cf_name}_completion", + "prog_name": prog_name, + "autocomplete_var": complete_var, + } ).strip() @@ -191,7 +191,7 @@ def install_powershell(*, prog_name: str, complete_var: str, shell: str) -> Path path_str = result.stdout.decode("utf8") except UnicodeDecodeError: click.echo("Couldn't decode the path automatically", err=True) - raise click.exceptions.Exit(1) + raise path_obj = Path(path_str.strip()) parent_dir: Path = path_obj.parent parent_dir.mkdir(parents=True, exist_ok=True) diff --git a/typer/_typing.py b/typer/_typing.py index bfa8114fcb..b1d2483da0 100644 --- a/typer/_typing.py +++ b/typer/_typing.py @@ -252,7 +252,7 @@ def convert_generics(tp: Type[Any]) -> Type[Any]: return _UnionGenericAlias(origin, converted) else: try: - setattr(tp, "__args__", converted) + setattr(tp, "__args__", converted) # noqa: B010 except AttributeError: pass return tp diff --git a/typer/core.py b/typer/core.py index c56acf8522..fd534483df 100644 --- a/typer/core.py +++ b/typer/core.py @@ -200,9 +200,9 @@ def _main( # even always obvious that `rv` indicates success/failure # by its truthiness/falsiness ctx.exit() - except (EOFError, KeyboardInterrupt): + except (EOFError, KeyboardInterrupt) as e: click.echo(file=sys.stderr) - raise click.Abort() + raise click.Abort() from e except click.ClickException as e: if not standalone_mode: raise @@ -370,7 +370,7 @@ def make_metavar(self) -> str: return self.metavar var = (self.name or "").upper() if not self.required: - var = "[{}]".format(var) + var = f"[{var}]" type_var = self.type.get_metavar(self) if type_var: var += f":{type_var}" diff --git a/typer/main.py b/typer/main.py index 21683d913a..88ccbc07b5 100644 --- a/typer/main.py +++ b/typer/main.py @@ -81,9 +81,7 @@ def except_hook( tb_exc = traceback.TracebackException.from_exception(exc) stack: List[FrameSummary] = [] for frame in tb_exc.stack: - if any( - [frame.filename.startswith(path) for path in supress_internal_dir_names] - ): + if any(frame.filename.startswith(path) for path in supress_internal_dir_names): if not exception_config.pretty_exceptions_short: # Hide the line for internal libraries, Typer and Click stack.append( @@ -370,7 +368,9 @@ def get_command(typer_instance: Typer) -> click.Command: click_command.params.append(click_install_param) click_command.params.append(click_show_param) return click_command - assert False, "Could not get a command for this Typer instance" # pragma no cover + raise RuntimeError( + "Could not get a command for this Typer instance" + ) # pragma no cover def get_group_name(typer_info: TyperInfo) -> Optional[str]: @@ -444,7 +444,8 @@ def solve_typer_info_defaults(typer_info: TyperInfo) -> TyperInfo: # Priority 2: Value was set in @subapp.callback() try: callback_value = getattr( - typer_info.typer_instance.registered_callback, name # type: ignore + typer_info.typer_instance.registered_callback, # type: ignore + name, ) if not isinstance(callback_value, DefaultPlaceholder): values[name] = callback_value @@ -454,7 +455,8 @@ def solve_typer_info_defaults(typer_info: TyperInfo) -> TyperInfo: # Priority 3: Value set in subapp = typer.Typer() try: instance_value = getattr( - typer_info.typer_instance.info, name # type: ignore + typer_info.typer_instance.info, # type: ignore + name, ) if not isinstance(instance_value, DefaultPlaceholder): values[name] = instance_value @@ -539,7 +541,7 @@ def get_command_name(name: str) -> str: def get_params_convertors_ctx_param_name_from_function( - callback: Optional[Callable[..., Any]] + callback: Optional[Callable[..., Any]], ) -> Tuple[List[Union[click.Argument, click.Option]], Dict[str, Any], Optional[str]]: params = [] convertors = {} @@ -659,10 +661,11 @@ def get_callback( *, callback: Optional[Callable[..., Any]] = None, params: Sequence[click.Parameter] = [], - convertors: Dict[str, Callable[[str], Any]] = {}, + convertors: Optional[Dict[str, Callable[[str], Any]]] = None, context_param_name: Optional[str] = None, pretty_exceptions_short: bool, ) -> Optional[Callable[..., Any]]: + use_convertors = convertors or {} if not callback: return None parameters = get_params_from_function(callback) @@ -676,8 +679,8 @@ def get_callback( def wrapper(**kwargs: Any) -> Any: _rich_traceback_guard = pretty_exceptions_short # noqa: F841 for k, v in kwargs.items(): - if k in convertors: - use_params[k] = convertors[k](v) + if k in use_convertors: + use_params[k] = use_convertors[k](v) else: use_params[k] = v if context_param_name: @@ -860,7 +863,7 @@ def get_click_param( if is_tuple: convertor = generate_tuple_convertor(main_type.__args__) if isinstance(parameter_info, OptionInfo): - if main_type is bool and not (parameter_info.is_flag is False): + if main_type is bool and parameter_info.is_flag is not False: is_flag = True # Click doesn't accept a flag of type bool, only None, and then it sets it # to bool internally @@ -946,7 +949,7 @@ def get_click_param( ), convertor, ) - assert False, "A click.Parameter should be returned" # pragma no cover + raise AssertionError("A click.Parameter should be returned") # pragma no cover def get_param_callback( @@ -1002,7 +1005,7 @@ def wrapper(ctx: click.Context, param: click.Parameter, value: Any) -> Any: def get_param_completion( - callback: Optional[Callable[..., Any]] = None + callback: Optional[Callable[..., Any]] = None, ) -> Optional[Callable[..., Any]]: if not callback: return None @@ -1010,7 +1013,7 @@ def get_param_completion( ctx_name = None args_name = None incomplete_name = None - unassigned_params = [param for param in parameters.values()] + unassigned_params = list(parameters.values()) for param_sig in unassigned_params[:]: origin = getattr(param_sig.annotation, "__origin__", None) if lenient_issubclass(param_sig.annotation, click.Context): From 4c051bc63928c6f266c1c6d7d665a708148b2006 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 21:45:39 +0000 Subject: [PATCH 12/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 1563c17dfa..b2939fab34 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -6,6 +6,10 @@ * 🔥 Remove support for Click 7, require Click 8+. PR [#760](https://github.com/tiangolo/typer/pull/760) by [@tiangolo](https://github.com/tiangolo). * 🔥 Remove support for Python 3.6. PR [#758](https://github.com/tiangolo/typer/pull/758) by [@tiangolo](https://github.com/tiangolo). +### Refactors + +* 🔧 Migrate from Black, isort, flake8, autoflake, pyupgrade to Ruff. PR [#763](https://github.com/tiangolo/typer/pull/763) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 👷 Upgrade Smokeshow GitHub action. PR [#767](https://github.com/tiangolo/typer/pull/767) by [@tiangolo](https://github.com/tiangolo). From c1dd6617d0b5067ada2b4e9f75da4c63a395a59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 17:14:10 -0500 Subject: [PATCH 13/37] =?UTF-8?q?=F0=9F=94=A7=20Upgrade=20mypy=20and=20con?= =?UTF-8?q?fig=20(#768)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mypy.ini | 6 ------ pyproject.toml | 14 ++++++++++++++ requirements-tests.txt | 2 +- scripts/lint.sh | 4 ++-- typer/core.py | 13 +++++++------ typer/main.py | 8 ++++---- 6 files changed, 28 insertions(+), 19 deletions(-) delete mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 45d34ea136..0000000000 --- a/mypy.ini +++ /dev/null @@ -1,6 +0,0 @@ -[mypy] -ignore_missing_imports = True - -[mypy-typer.*] -disallow_untyped_defs = True -strict = True diff --git a/pyproject.toml b/pyproject.toml index 44b71f3efd..51ccd62921 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ all = [ [tool.pdm] version = { source = "file", path = "typer/__init__.py" } +distribution = true [tool.isort] profile = "black" @@ -75,6 +76,19 @@ filterwarnings = [ 'ignore::DeprecationWarning:xdist', ] +[tool.mypy] +strict = true + +[[tool.mypy.overrides]] +module = "docs_src.*" +disallow_incomplete_defs = false +disallow_untyped_defs = false +disallow_untyped_calls = false + +[[tool.mypy.overrides]] +module = "shellingham" +ignore_missing_imports = true + [tool.ruff.lint] select = [ "E", # pycodestyle errors diff --git a/requirements-tests.txt b/requirements-tests.txt index 74ba25fb41..f15e480ffc 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -5,5 +5,5 @@ pytest-cov >=2.10.0,<5.0.0 coverage[toml] >=6.2,<7.0 pytest-xdist >=1.32.0,<4.0.0 pytest-sugar >=0.9.4,<0.10.0 -mypy ==0.971 +mypy ==1.4.1 ruff ==0.2.0 diff --git a/scripts/lint.sh b/scripts/lint.sh index aa2c982271..a32cf3afca 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,5 +4,5 @@ set -e set -x mypy typer -ruff typer tests docs_src scripts -ruff format typer tests --check +ruff typer tests docs_src +ruff format typer tests docs_src --check diff --git a/typer/core.py b/typer/core.py index fd534483df..6c0f70f94f 100644 --- a/typer/core.py +++ b/typer/core.py @@ -77,14 +77,15 @@ def compat_autocompletion( out = [] - for c in autocompletion(ctx, [], incomplete): # type: ignore + for c in autocompletion(ctx, [], incomplete): if isinstance(c, tuple): - c = CompletionItem(c[0], help=c[1]) - elif isinstance(c, str): - c = CompletionItem(c) + use_completion = CompletionItem(c[0], help=c[1]) + else: + assert isinstance(c, str) + use_completion = CompletionItem(c) - if c.value.startswith(incomplete): - out.append(c) + if use_completion.value.startswith(incomplete): + out.append(use_completion) return out diff --git a/typer/main.py b/typer/main.py index 88ccbc07b5..414a5d2ee5 100644 --- a/typer/main.py +++ b/typer/main.py @@ -95,7 +95,7 @@ def except_hook( else: stack.append(frame) # Type ignore ref: https://github.com/python/typeshed/pull/8244 - final_stack_summary = StackSummary.from_list(stack) # type: ignore + final_stack_summary = StackSummary.from_list(stack) tb_exc.stack = final_stack_summary for line in tb_exc.format(): print(line, file=sys.stderr) @@ -685,7 +685,7 @@ def wrapper(**kwargs: Any) -> Any: use_params[k] = v if context_param_name: use_params[context_param_name] = click.get_current_context() - return callback(**use_params) # type: ignore + return callback(**use_params) update_wrapper(wrapper, callback) return wrapper @@ -998,7 +998,7 @@ def wrapper(ctx: click.Context, param: click.Parameter, value: Any) -> Any: else: use_value = value use_params[value_name] = use_value - return callback(**use_params) # type: ignore + return callback(**use_params) update_wrapper(wrapper, callback) return wrapper @@ -1051,7 +1051,7 @@ def wrapper(ctx: click.Context, args: List[str], incomplete: Optional[str]) -> A use_params[args_name] = args if incomplete_name: use_params[incomplete_name] = incomplete - return callback(**use_params) # type: ignore + return callback(**use_params) update_wrapper(wrapper, callback) return wrapper From 2d4c4c9c41e263d369ca1b805e26af14c53d38d1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 22:14:27 +0000 Subject: [PATCH 14/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index b2939fab34..a1eea3dc6a 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -12,6 +12,7 @@ ### Internal +* 🔧 Upgrade mypy and config. PR [#768](https://github.com/tiangolo/typer/pull/768) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade Smokeshow GitHub action. PR [#767](https://github.com/tiangolo/typer/pull/767) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade latest-changes GitHub Action. PR [#766](https://github.com/tiangolo/typer/pull/766) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade issue-manager GitHub Action. PR [#765](https://github.com/tiangolo/typer/pull/765) by [@tiangolo](https://github.com/tiangolo). From 71bdae18dc5ef7cccd9fffb75645c7ead4a4ce8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 17:32:14 -0500 Subject: [PATCH 15/37] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20coverage?= =?UTF-8?q?=20and=20configs=20(#769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .coveragerc | 23 ------------------- .gitignore | 1 + pyproject.toml | 21 +++++++++++++++++ requirements-tests.txt | 2 +- scripts/test.sh | 2 +- tests/test_completion/test_completion.py | 2 +- .../test_completion_install.py | 4 ++-- tests/test_others.py | 10 ++++---- .../test_file/test_tutorial002.py | 2 +- .../test_file/test_tutorial002_an.py | 2 +- .../test_file/test_tutorial004.py | 2 +- .../test_file/test_tutorial004_an.py | 2 +- .../test_file/test_tutorial005.py | 2 +- .../test_file/test_tutorial005_an.py | 2 +- .../test_path/test_tutorial001.py | 2 +- .../test_path/test_tutorial001_an.py | 2 +- .../test_path/test_tutorial002.py | 2 +- .../test_path/test_tutorial002_an.py | 2 +- typer/_completion_classes.py | 2 +- typer/_completion_shared.py | 12 +++++----- typer/completion.py | 10 ++++---- typer/core.py | 2 +- typer/main.py | 8 +++---- 23 files changed, 59 insertions(+), 60 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index fac0faafa0..0000000000 --- a/.coveragerc +++ /dev/null @@ -1,23 +0,0 @@ -[run] - -source = - typer - tests - docs_src - -omit = - typer/_typing.py - -parallel = True -context = '${CONTEXT}' - -[report] -precision = 2 -exclude_lines = - pragma: no cover - pragma: nocover - pragma no cover - raise NotImplementedError - raise NotImplemented - @overload - if TYPE_CHECKING: diff --git a/.gitignore b/.gitignore index c4f1d90825..a18be48595 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ site htmlcov .pytest_cache coverage.xml +.coverage* diff --git a/pyproject.toml b/pyproject.toml index 51ccd62921..280cd16412 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,27 @@ filterwarnings = [ 'ignore::DeprecationWarning:xdist', ] +[tool.coverage.run] +parallel = true +data_file = "coverage/.coverage" +source = [ + "docs_src", + "tests", + "typer" +] +omit = [ + "typer/_typing.py" +] +context = '${CONTEXT}' + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "@overload", + 'if __name__ == "__main__":', + "if TYPE_CHECKING:", +] + [tool.mypy] strict = true diff --git a/requirements-tests.txt b/requirements-tests.txt index f15e480ffc..f89c88eebe 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -2,7 +2,7 @@ pytest >=4.4.0,<8.0.0 pytest-cov >=2.10.0,<5.0.0 -coverage[toml] >=6.2,<7.0 +coverage[toml] >=6.2,<8.0 pytest-xdist >=1.32.0,<4.0.0 pytest-sugar >=0.9.4,<0.10.0 mypy ==1.4.1 diff --git a/scripts/test.sh b/scripts/test.sh index 742e51a523..f0a7c9c779 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -9,4 +9,4 @@ export TERMINAL_WIDTH=3000 export _TYPER_FORCE_DISABLE_TERMINAL=1 bash ./scripts/test-files.sh # It seems xdist-pytest ensures modified sys.path to import relative modules in examples keeps working -pytest --cov-config=.coveragerc --cov --cov-report=term-missing -o console_output_style=progress --numprocesses=auto ${@} +pytest --cov --cov-report=term-missing -o console_output_style=progress --numprocesses=auto ${@} diff --git a/tests/test_completion/test_completion.py b/tests/test_completion/test_completion.py index ae5972a584..9f5dd426db 100644 --- a/tests/test_completion/test_completion.py +++ b/tests/test_completion/test_completion.py @@ -23,7 +23,7 @@ def test_show_completion(): def test_install_completion(): bash_completion_path: Path = Path.home() / ".bashrc" text = "" - if bash_completion_path.is_file(): # pragma: nocover + if bash_completion_path.is_file(): # pragma: no cover text = bash_completion_path.read_text() result = subprocess.run( [ diff --git a/tests/test_completion/test_completion_install.py b/tests/test_completion/test_completion_install.py index e823e388e4..7a3eac4a77 100644 --- a/tests/test_completion/test_completion_install.py +++ b/tests/test_completion/test_completion_install.py @@ -72,7 +72,7 @@ def test_completion_install_bash(): def test_completion_install_zsh(): completion_path: Path = Path.home() / ".zshrc" text = "" - if not completion_path.is_file(): # pragma: nocover + if not completion_path.is_file(): # pragma: no cover completion_path.write_text('echo "custom .zshrc"') if completion_path.is_file(): text = completion_path.read_text() @@ -148,7 +148,7 @@ def test_completion_install_powershell(): ) completion_path_bytes = f"{completion_path}\n".encode("windows-1252") text = "" - if completion_path.is_file(): # pragma: nocover + if completion_path.is_file(): # pragma: no cover text = completion_path.read_text() with mock.patch.object( diff --git a/tests/test_others.py b/tests/test_others.py index 12fa0ae09b..367a8caeba 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -94,11 +94,11 @@ def test_callback_too_many_parameters(): app = typer.Typer() def name_callback(ctx, param, val1, val2): - pass # pragma: nocover + pass # pragma: no cover @app.command() def main(name: str = typer.Option(..., callback=name_callback)): - pass # pragma: nocover + pass # pragma: no cover with pytest.raises(click.ClickException) as exc_info: runner.invoke(app, ["--name", "Camila"]) @@ -199,11 +199,11 @@ def test_autocompletion_too_many_parameters(): app = typer.Typer() def name_callback(ctx, args, incomplete, val2): - pass # pragma: nocover + pass # pragma: no cover @app.command() def main(name: str = typer.Option(..., autocompletion=name_callback)): - pass # pragma: nocover + pass # pragma: no cover with pytest.raises(click.ClickException) as exc_info: runner.invoke(app, ["--name", "Camila"]) @@ -236,7 +236,7 @@ def test_context_settings_inheritance_single_command(): @app.command() def main(name: str): - pass # pragma: nocover + pass # pragma: no cover result = runner.invoke(app, ["main", "-h"]) assert "Show this message and exit." in result.stdout diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py index 5b6549b380..0f6ff64209 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002.py @@ -15,7 +15,7 @@ def test_main(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) text = config_file.read_text() diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py index fcddf8f6c2..c2f605d84e 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial002_an.py @@ -15,7 +15,7 @@ def test_main(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) text = config_file.read_text() diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py index 6821a5e1b8..3182d7b4ed 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004.py @@ -15,7 +15,7 @@ def test_main(tmpdir): binary_file = Path(tmpdir) / "config.txt" - if binary_file.exists(): # pragma no cover + if binary_file.exists(): # pragma: no cover binary_file.unlink() result = runner.invoke(app, ["--file", f"{binary_file}"]) text = binary_file.read_text() diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py index f56d8c6f93..e222d7160c 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial004_an.py @@ -15,7 +15,7 @@ def test_main(tmpdir): binary_file = Path(tmpdir) / "config.txt" - if binary_file.exists(): # pragma no cover + if binary_file.exists(): # pragma: no cover binary_file.unlink() result = runner.invoke(app, ["--file", f"{binary_file}"]) text = binary_file.read_text() diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py index 8c1b3b7fff..bdc52c8381 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005.py @@ -15,7 +15,7 @@ def test_main(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() config_file.write_text("") result = runner.invoke(app, ["--config", f"{config_file}"]) diff --git a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py index bd39911425..85d49e121e 100644 --- a/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py +++ b/tests/test_tutorial/test_parameter_types/test_file/test_tutorial005_an.py @@ -15,7 +15,7 @@ def test_main(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() config_file.write_text("") result = runner.invoke(app, ["--config", f"{config_file}"]) diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py index 4ad4d2ead5..e15121586f 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001.py @@ -23,7 +23,7 @@ def test_no_path(tmpdir): def test_not_exists(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) assert result.exit_code == 0 diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py index 7c4699186d..1db306f8d5 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial001_an.py @@ -23,7 +23,7 @@ def test_no_path(tmpdir): def test_not_exists(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) assert result.exit_code == 0 diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py index 069c24a910..e9dadce492 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002.py @@ -15,7 +15,7 @@ def test_not_exists(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) assert result.exit_code != 0 diff --git a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py index 54d79ccaf8..b727e4de55 100644 --- a/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py +++ b/tests/test_tutorial/test_parameter_types/test_path/test_tutorial002_an.py @@ -15,7 +15,7 @@ def test_not_exists(tmpdir): config_file = Path(tmpdir) / "config.txt" - if config_file.exists(): # pragma no cover + if config_file.exists(): # pragma: no cover config_file.unlink() result = runner.invoke(app, ["--config", f"{config_file}"]) assert result.exit_code != 0 diff --git a/typer/_completion_classes.py b/typer/_completion_classes.py index 54e2b03d6f..6bb25c13bd 100644 --- a/typer/_completion_classes.py +++ b/typer/_completion_classes.py @@ -17,7 +17,7 @@ try: import shellingham -except ImportError: # pragma: nocover +except ImportError: # pragma: no cover shellingham = None diff --git a/typer/_completion_shared.py b/typer/_completion_shared.py index 1fb82e8406..10de54420d 100644 --- a/typer/_completion_shared.py +++ b/typer/_completion_shared.py @@ -9,7 +9,7 @@ try: import shellingham -except ImportError: # pragma: nocover +except ImportError: # pragma: no cover shellingham = None @@ -108,7 +108,7 @@ def install_bash(*, prog_name: str, complete_var: str, shell: str) -> Path: rc_content = rc_path.read_text() completion_init_lines = [f"source {completion_path}"] for line in completion_init_lines: - if line not in rc_content: # pragma: nocover + if line not in rc_content: # pragma: no cover rc_content += f"\n{line}" rc_content += "\n" rc_path.write_text(rc_content) @@ -135,7 +135,7 @@ def install_zsh(*, prog_name: str, complete_var: str, shell: str) -> Path: "fpath+=~/.zfunc", ] for line in completion_init_lines: - if line not in zshrc_content: # pragma: nocover + if line not in zshrc_content: # pragma: no cover zshrc_content += f"\n{line}" zshrc_content += "\n" zshrc_path.write_text(zshrc_content) @@ -176,17 +176,17 @@ def install_powershell(*, prog_name: str, complete_var: str, shell: str) -> Path check=True, stdout=subprocess.PIPE, ) - if result.returncode != 0: # pragma: nocover + if result.returncode != 0: # pragma: no cover click.echo("Couldn't get PowerShell user profile", err=True) raise click.exceptions.Exit(result.returncode) path_str = "" - if isinstance(result.stdout, str): # pragma: nocover + if isinstance(result.stdout, str): # pragma: no cover path_str = result.stdout if isinstance(result.stdout, bytes): try: # PowerShell would be predominant in Windows path_str = result.stdout.decode("windows-1252") - except UnicodeDecodeError: # pragma: nocover + except UnicodeDecodeError: # pragma: no cover try: path_str = result.stdout.decode("utf8") except UnicodeDecodeError: diff --git a/typer/completion.py b/typer/completion.py index fce42965d3..1220a1b545 100644 --- a/typer/completion.py +++ b/typer/completion.py @@ -12,7 +12,7 @@ try: import shellingham -except ImportError: # pragma: nocover +except ImportError: # pragma: no cover shellingham = None @@ -34,7 +34,7 @@ def get_completion_inspect_parameters() -> Tuple[ParamMeta, ParamMeta]: def install_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: if not value or ctx.resilient_parsing: - return value # pragma no cover + return value # pragma: no cover if isinstance(value, str): shell, path = install(shell=value) else: @@ -46,7 +46,7 @@ def install_callback(ctx: click.Context, param: click.Parameter, value: Any) -> def show_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: if not value or ctx.resilient_parsing: - return value # pragma no cover + return value # pragma: no cover prog_name = ctx.find_root().info_name assert prog_name complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) @@ -82,7 +82,7 @@ def _install_completion_placeholder_function( help="Show completion for the current shell, to copy it or customize the installation.", ), ) -> Any: - pass # pragma no cover + pass # pragma: no cover def _install_completion_no_auto_placeholder_function( @@ -99,7 +99,7 @@ def _install_completion_no_auto_placeholder_function( help="Show completion for the specified shell, to copy it or customize the installation.", ), ) -> Any: - pass # pragma no cover + pass # pragma: no cover # Re-implement Click's shell_complete to add error message with: diff --git a/typer/core.py b/typer/core.py index 6c0f70f94f..31fece5a76 100644 --- a/typer/core.py +++ b/typer/core.py @@ -36,7 +36,7 @@ from . import rich_utils -except ImportError: # pragma: nocover +except ImportError: # pragma: no cover rich = None # type: ignore MarkupMode = Literal["markdown", "rich", None] diff --git a/typer/main.py b/typer/main.py index 414a5d2ee5..ccf9f0956c 100644 --- a/typer/main.py +++ b/typer/main.py @@ -43,7 +43,7 @@ console_stderr = Console(stderr=True) -except ImportError: # pragma: nocover +except ImportError: # pragma: no cover rich = None # type: ignore _original_except_hook = sys.excepthook @@ -370,7 +370,7 @@ def get_command(typer_instance: Typer) -> click.Command: return click_command raise RuntimeError( "Could not get a command for this Typer instance" - ) # pragma no cover + ) # pragma: no cover def get_group_name(typer_info: TyperInfo) -> Optional[str]: @@ -781,7 +781,7 @@ def get_click_type( [item.value for item in annotation], case_sensitive=parameter_info.case_sensitive, ) - raise RuntimeError(f"Type not yet supported: {annotation}") # pragma no cover + raise RuntimeError(f"Type not yet supported: {annotation}") # pragma: no cover def lenient_issubclass( @@ -949,7 +949,7 @@ def get_click_param( ), convertor, ) - raise AssertionError("A click.Parameter should be returned") # pragma no cover + raise AssertionError("A click.Parameter should be returned") # pragma: no cover def get_param_callback( From da7d015b57f6dc7552cf23c18cdc6866ca2e93a5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 26 Mar 2024 22:32:31 +0000 Subject: [PATCH 16/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index a1eea3dc6a..1918ba248f 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -12,6 +12,7 @@ ### Internal +* ⬆️ Upgrade coverage and configs. PR [#769](https://github.com/tiangolo/typer/pull/769) by [@tiangolo](https://github.com/tiangolo). * 🔧 Upgrade mypy and config. PR [#768](https://github.com/tiangolo/typer/pull/768) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade Smokeshow GitHub action. PR [#767](https://github.com/tiangolo/typer/pull/767) by [@tiangolo](https://github.com/tiangolo). * 👷 Upgrade latest-changes GitHub Action. PR [#766](https://github.com/tiangolo/typer/pull/766) by [@tiangolo](https://github.com/tiangolo). From 1f6b15e71a66466046a95287d07b16070d6121ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 26 Mar 2024 17:33:24 -0500 Subject: [PATCH 17/37] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 2 ++ typer/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index 1918ba248f..7a9eb4926d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,7 @@ ## Latest Changes +## 0.11.0 + ### Breaking Changes * 🔧 Refactor package manager, move from Flit to PDM, remove private pip extras for `test`, `doc`, `dev`. PR [#764](https://github.com/tiangolo/typer/pull/764) by [@tiangolo](https://github.com/tiangolo). diff --git a/typer/__init__.py b/typer/__init__.py index 3ffa8c384b..2c4817d5e2 100644 --- a/typer/__init__.py +++ b/typer/__init__.py @@ -1,6 +1,6 @@ """Typer, build great CLIs. Easy to code. Based on Python type hints.""" -__version__ = "0.10.0" +__version__ = "0.11.0" from shutil import get_terminal_size as get_terminal_size From 0cdc31e6cc75aecbace7cb7dc6a28b66899d0326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 28 Mar 2024 18:10:37 -0500 Subject: [PATCH 18/37] =?UTF-8?q?=F0=9F=94=A7=20Explicitly=20include=20tes?= =?UTF-8?q?ting=20files=20in=20sdist=20for=20redistributors=20(e.g.=20Open?= =?UTF-8?q?SUSE)=20and=20add=20CI=20to=20test=20redistribution=20(#773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-redistribute.yml | 51 +++++++++++++++++++++++++ .github/workflows/test.yml | 1 + pyproject.toml | 8 ++++ scripts/test.sh | 1 - 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test-redistribute.yml diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml new file mode 100644 index 0000000000..9ef1cde73c --- /dev/null +++ b/.github/workflows/test-redistribute.yml @@ -0,0 +1,51 @@ +name: Test Redistribute + +on: + push: + branches: + - master + pull_request: + types: + - opened + - synchronize + +jobs: + test-redistribute: + runs-on: ubuntu-latest + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" + # cache-dependency-path: pyproject.toml + - name: Install build dependencies + run: pip install build + - name: Build source distribution + run: python -m build --sdist + - name: Decompress source distribution + run: | + cd dist + tar xvf typer*.tar.gz + - name: Install test dependencies + run: | + cd dist/typer-*/ + pip install -r requirements-tests.txt + - name: Run source distribution tests + run: | + cd dist/typer-*/ + bash scripts/test.sh + - name: Build wheel distribution + run: | + cd dist + pip wheel --no-deps typer-*.tar.gz + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8fcc70910e..6cef6278ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,7 @@ jobs: - name: Lint run: bash scripts/lint.sh - run: mkdir coverage + - run: bash ./scripts/test-files.sh - name: Test run: bash scripts/test.sh env: diff --git a/pyproject.toml b/pyproject.toml index 280cd16412..2ae5002fc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,14 @@ all = [ version = { source = "file", path = "typer/__init__.py" } distribution = true +[tool.pdm.build] +source-includes = [ + "tests/", + "docs_src/", + "requirements*.txt", + "scripts/", + ] + [tool.isort] profile = "black" known_third_party = ["typer", "click"] diff --git a/scripts/test.sh b/scripts/test.sh index f0a7c9c779..32fa1e73f3 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -7,6 +7,5 @@ set -x export TERMINAL_WIDTH=3000 # Force disable terminal for tests inside of pytest, takes precedence over GITHUB_ACTIONS env var export _TYPER_FORCE_DISABLE_TERMINAL=1 -bash ./scripts/test-files.sh # It seems xdist-pytest ensures modified sys.path to import relative modules in examples keeps working pytest --cov --cov-report=term-missing -o console_output_style=progress --numprocesses=auto ${@} From 6de764648c2682246c5d1b34b59f88c25f295b8a Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 28 Mar 2024 23:10:56 +0000 Subject: [PATCH 19/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 7a9eb4926d..a5419d542c 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,9 @@ ## Latest Changes +### Fixes + +* 🔧 Explicitly include testing files in sdist for redistributors (e.g. OpenSUSE) and add CI to test redistribution. PR [#773](https://github.com/tiangolo/typer/pull/773) by [@tiangolo](https://github.com/tiangolo). + ## 0.11.0 ### Breaking Changes From 4b60ed66b50e0ecb8c126d28465ea3b6a6b83683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 28 Mar 2024 18:17:03 -0500 Subject: [PATCH 20/37] =?UTF-8?q?=F0=9F=91=B7=20Do=20not=20use=20the=20cac?= =?UTF-8?q?he=20for=20dependencies=20when=20publishing=20to=20PyPI=20(#774?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bc72a0ed72..899e49057f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,13 +21,7 @@ jobs: # Issue ref: https://github.com/actions/setup-python/issues/436 # cache: "pip" # cache-dependency-path: pyproject.toml - - uses: actions/cache@v3 - id: cache - with: - path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }} - name: Install build dependencies - if: steps.cache.outputs.cache-hit != 'true' run: pip install build - name: Build distribution run: python -m build From f858db60384dd37690a37c16d5653c1e9b67c9ec Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 28 Mar 2024 23:17:22 +0000 Subject: [PATCH 21/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index a5419d542c..bebc93ddf3 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,10 @@ * 🔧 Explicitly include testing files in sdist for redistributors (e.g. OpenSUSE) and add CI to test redistribution. PR [#773](https://github.com/tiangolo/typer/pull/773) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* 👷 Do not use the cache for dependencies when publishing to PyPI. PR [#774](https://github.com/tiangolo/typer/pull/774) by [@tiangolo](https://github.com/tiangolo). + ## 0.11.0 ### Breaking Changes From 73efcb3c24042575bcc80665f47d214cbfd6a149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 28 Mar 2024 18:20:31 -0500 Subject: [PATCH 22/37] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 2 ++ typer/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index bebc93ddf3..5d656a8376 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,7 @@ ## Latest Changes +## 0.11.1 + ### Fixes * 🔧 Explicitly include testing files in sdist for redistributors (e.g. OpenSUSE) and add CI to test redistribution. PR [#773](https://github.com/tiangolo/typer/pull/773) by [@tiangolo](https://github.com/tiangolo). diff --git a/typer/__init__.py b/typer/__init__.py index 2c4817d5e2..a659d767b6 100644 --- a/typer/__init__.py +++ b/typer/__init__.py @@ -1,6 +1,6 @@ """Typer, build great CLIs. Easy to code. Based on Python type hints.""" -__version__ = "0.11.0" +__version__ = "0.11.1" from shutil import get_terminal_size as get_terminal_size From 19efa77bc390a5510bc52d83e6330c00c51c01bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 29 Mar 2024 15:25:53 -0500 Subject: [PATCH 23/37] =?UTF-8?q?=F0=9F=91=B7=20Fix=20install=20MkDocs=20I?= =?UTF-8?q?nsiders=20only=20when=20available=20(#778)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index b8b2164354..9e448c374c 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -53,12 +53,12 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v01 + key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v02 - name: Install docs extras if: steps.cache.outputs.cache-hit != 'true' run: pip install -r requirements-docs.txt - name: Install Material for MkDocs Insiders - if: ( github.event_name != 'pull_request' || github.secret_source != 'Actions' ) && steps.cache.outputs.cache-hit != 'true' + if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true' run: | pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git pip install git+https://${{ secrets.TYPER_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git @@ -71,7 +71,7 @@ jobs: if: github.event_name == 'pull_request' && github.secret_source != 'Actions' run: python -m mkdocs build - name: Build Docs with Insiders - if: ( github.event_name != 'pull_request' || github.secret_source != 'Actions' ) + if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) run: python -m mkdocs build --config-file mkdocs.insiders.yml - uses: actions/upload-artifact@v3 From db27196d0dcd6ff67fd9a4c1562869d3867d4116 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 29 Mar 2024 20:26:13 +0000 Subject: [PATCH 24/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 5d656a8376..e5e5e15f86 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,9 @@ ## Latest Changes +### Internal + +* 👷 Fix install MkDocs Insiders only when available. PR [#778](https://github.com/tiangolo/typer/pull/778) by [@tiangolo](https://github.com/tiangolo). + ## 0.11.1 ### Fixes From 2ab3c262dfa5b241c80cee97a1784fe65c21d079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 29 Mar 2024 15:43:31 -0500 Subject: [PATCH 25/37] =?UTF-8?q?=F0=9F=94=A7=20Temporarily=20disable=20so?= =?UTF-8?q?cial=20plugin=20while=20a=20MkDocs=20issue=20is=20handled=20(#7?= =?UTF-8?q?79)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mkdocs.insiders.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkdocs.insiders.yml b/mkdocs.insiders.yml index 9f2775ff97..7c1870afb7 100644 --- a/mkdocs.insiders.yml +++ b/mkdocs.insiders.yml @@ -1,4 +1,5 @@ INHERIT: mkdocs.yml plugins: - search - - social + # TODO: Re-enable once this is fixed: https://github.com/squidfunk/mkdocs-material/issues/6983 + # - social From 62988dfa00b8e0778fda697768f8a9e5e5715eed Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 29 Mar 2024 20:43:53 +0000 Subject: [PATCH 26/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index e5e5e15f86..48ed28ad12 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,7 @@ ### Internal +* 🔧 Temporarily disable social plugin while a MkDocs issue is handled. PR [#779](https://github.com/tiangolo/typer/pull/779) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix install MkDocs Insiders only when available. PR [#778](https://github.com/tiangolo/typer/pull/778) by [@tiangolo](https://github.com/tiangolo). ## 0.11.1 From 7d5d6bb9e6eed6ef53271e78727b467f362504c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 29 Mar 2024 21:09:05 -0500 Subject: [PATCH 27/37] =?UTF-8?q?=E2=9C=A8=20Add=20`typer-slim`=20package?= =?UTF-8?q?=20without=20extras,=20make=20`typer`=20include=20`typer-slim[d?= =?UTF-8?q?efault]`=20and=20integrate=20Typer=20CLI=20(`typer`=20command)?= =?UTF-8?q?=20into=20Typer=20(#780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish.yml | 17 +- .github/workflows/test-redistribute.yml | 23 +- README.md | 117 +++++-- docs/features.md | 8 +- docs/index.md | 117 +++++-- docs/tutorial/first-steps.md | 10 +- docs/tutorial/index.md | 23 +- docs/tutorial/options-autocompletion.md | 8 +- docs/tutorial/options/callback-and-context.md | 4 +- docs/tutorial/package.md | 11 +- docs/tutorial/printing.md | 22 +- .../typer-command.md} | 128 +++----- mkdocs.insiders.yml | 3 +- mkdocs.yml | 7 +- pyproject.toml | 13 +- tests/assets/cli/__init__.py | 0 tests/assets/cli/app_other_name.py | 8 + tests/assets/cli/empty_script.py | 0 tests/assets/cli/func_other_name.py | 2 + tests/assets/cli/multi_app.py | 40 +++ tests/assets/cli/multi_app_cli.py | 22 ++ tests/assets/cli/multi_func.py | 12 + tests/assets/cli/multiapp-docs.md | 102 ++++++ tests/assets/cli/not_python.txt | 1 + tests/assets/cli/sample.py | 25 ++ tests/test_cli/__init__.py | 0 tests/test_cli/test_app_other_name.py | 41 +++ tests/test_cli/test_completion_run.py | 19 ++ tests/test_cli/test_doc.py | 112 +++++++ tests/test_cli/test_empty_script.py | 20 ++ tests/test_cli/test_func_other_name.py | 22 ++ tests/test_cli/test_help.py | 38 +++ tests/test_cli/test_multi_app.py | 123 ++++++++ tests/test_cli/test_multi_app_cli.py | 102 ++++++ tests/test_cli/test_multi_app_sub.py | 46 +++ tests/test_cli/test_multi_func.py | 106 +++++++ tests/test_cli/test_not_python.py | 20 ++ tests/test_cli/test_sub.py | 139 +++++++++ tests/test_cli/test_sub_completion.py | 19 ++ tests/test_cli/test_sub_help.py | 24 ++ tests/test_cli/test_version.py | 11 + tests/test_compat/test_option_get_help.py | 1 - tests/test_completion/test_completion.py | 8 - .../test_completion_complete.py | 10 - .../test_completion_complete_no_help.py | 4 - .../test_completion_install.py | 4 - tests/test_completion/test_completion_show.py | 6 - tests/test_others.py | 2 - .../test_callback/test_tutorial003.py | 1 - .../test_callback/test_tutorial003_an.py | 1 - .../test_callback/test_tutorial004.py | 1 - .../test_callback/test_tutorial004_an.py | 1 - .../test_version/test_tutorial003.py | 1 - .../test_version/test_tutorial003_an.py | 1 - .../test_tutorial002.py | 1 - .../test_tutorial002_an.py | 1 - .../test_tutorial003.py | 1 - .../test_tutorial003_an.py | 1 - .../test_tutorial004.py | 1 - .../test_tutorial004_an.py | 1 - .../test_tutorial007.py | 1 - .../test_tutorial007_an.py | 1 - .../test_tutorial008.py | 1 - .../test_tutorial008_an.py | 1 - .../test_tutorial009.py | 1 - .../test_tutorial009_an.py | 1 - typer/__init__.py | 2 +- typer/__main__.py | 3 + typer/cli.py | 292 ++++++++++++++++++ typer_cli_package/README.md | 49 +++ typer_cli_package/pdm_build.py | 40 +++ typer_cli_package/pyproject.toml | 55 ++++ typer_package/pdm_build.py | 49 +++ typer_package/pyproject.toml | 52 ++++ 74 files changed, 1900 insertions(+), 260 deletions(-) rename docs/{typer-cli.md => tutorial/typer-command.md} (61%) create mode 100644 tests/assets/cli/__init__.py create mode 100644 tests/assets/cli/app_other_name.py create mode 100644 tests/assets/cli/empty_script.py create mode 100644 tests/assets/cli/func_other_name.py create mode 100644 tests/assets/cli/multi_app.py create mode 100644 tests/assets/cli/multi_app_cli.py create mode 100644 tests/assets/cli/multi_func.py create mode 100644 tests/assets/cli/multiapp-docs.md create mode 100644 tests/assets/cli/not_python.txt create mode 100644 tests/assets/cli/sample.py create mode 100644 tests/test_cli/__init__.py create mode 100644 tests/test_cli/test_app_other_name.py create mode 100644 tests/test_cli/test_completion_run.py create mode 100644 tests/test_cli/test_doc.py create mode 100644 tests/test_cli/test_empty_script.py create mode 100644 tests/test_cli/test_func_other_name.py create mode 100644 tests/test_cli/test_help.py create mode 100644 tests/test_cli/test_multi_app.py create mode 100644 tests/test_cli/test_multi_app_cli.py create mode 100644 tests/test_cli/test_multi_app_sub.py create mode 100644 tests/test_cli/test_multi_func.py create mode 100644 tests/test_cli/test_not_python.py create mode 100644 tests/test_cli/test_sub.py create mode 100644 tests/test_cli/test_sub_completion.py create mode 100644 tests/test_cli/test_sub_help.py create mode 100644 tests/test_cli/test_version.py create mode 100644 typer/__main__.py create mode 100644 typer/cli.py create mode 100644 typer_cli_package/README.md create mode 100644 typer_cli_package/pdm_build.py create mode 100644 typer_cli_package/pyproject.toml create mode 100644 typer_package/pdm_build.py create mode 100644 typer_package/pyproject.toml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 899e49057f..1a842c4ea7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,6 +8,16 @@ on: jobs: publish: runs-on: ubuntu-latest + strategy: + matrix: + package: + - typer-slim + - typer + - typer-cli + env: + dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} + permissions: + id-token: write steps: - name: Dump GitHub context env: @@ -24,12 +34,9 @@ jobs: - name: Install build dependencies run: pip install build - name: Build distribution + working-directory: ${{ env.dir }} run: python -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.8.11 with: - password: ${{ secrets.PYPI_API_TOKEN }} - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" + packages-dir: ${{ env.dir }}/dist/ diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 9ef1cde73c..c16d19d7b4 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -12,6 +12,14 @@ on: jobs: test-redistribute: runs-on: ubuntu-latest + strategy: + matrix: + package: + - typer-slim + - typer + - typer-cli + env: + dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} steps: - name: Dump GitHub context env: @@ -28,24 +36,25 @@ jobs: - name: Install build dependencies run: pip install build - name: Build source distribution + working-directory: ${{ env.dir }} run: python -m build --sdist - name: Decompress source distribution + working-directory: ${{ env.dir }} run: | cd dist tar xvf typer*.tar.gz - name: Install test dependencies + if: ${{ matrix.package == 'typer-slim' }} run: | - cd dist/typer-*/ + cd dist/typer*/ pip install -r requirements-tests.txt - name: Run source distribution tests + if: ${{ matrix.package == 'typer-slim' }} run: | - cd dist/typer-*/ + cd dist/typer*/ bash scripts/test.sh - name: Build wheel distribution + working-directory: ${{ env.dir }} run: | cd dist - pip wheel --no-deps typer-*.tar.gz - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" + pip wheel --no-deps typer*.tar.gz diff --git a/README.md b/README.md index 303774709f..0d4d824aa1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ Typer is a library for building CLI applications that users will **love using** and developers will **love creating**. Based on Python type hints. +It's also a command line tool to run scripts, automatically converting them to CLI applications. + The key features are: * **Intuitive to write**: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs. @@ -35,39 +37,87 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **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. +* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs - - -**Typer** is FastAPI's little sibling. - -And it's intended to be the FastAPI of CLIs. - -## Requirements - -**Typer** stands on the shoulders of a giant. Its only internal dependency is Click. +**Typer** is FastAPI's little sibling, it's the FastAPI of CLIs. ## Installation
```console -$ pip install "typer[all]" +$ pip install typer ---> 100% -Successfully installed typer +Successfully installed typer rich shellingham ```
-**Note**: that will include Rich. Rich is the recommended library to *display* information on the terminal, it is optional, but when installed, it's deeply integrated into **Typer** to display beautiful output. - ## Example ### The absolute minimum * Create a file `main.py` with: +```Python +def main(name: str): + print(f"Hello {name}") +``` + +This script doesn't even use Typer internally. But you can use the `typer` command to run it as a CLI application. + +### Run it + +Run your application with the `typer` command: + +
+ +```console +// Run your application +$ typer main.py run + +// You get a nice error, you are missing NAME +Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +Try 'typer [PATH_OR_MODULE] run --help' for help. +╭─ Error ───────────────────────────────────────────╮ +│ Missing argument 'NAME'. │ +╰───────────────────────────────────────────────────╯ + + +// You get a --help for free +$ typer main.py run --help + +Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME + +Run the provided Typer app. + +╭─ Arguments ───────────────────────────────────────╮ +│ * name TEXT [default: None] [required] | +╰───────────────────────────────────────────────────╯ +╭─ Options ─────────────────────────────────────────╮ +│ --help Show this message and exit. │ +╰───────────────────────────────────────────────────╯ + +// Now pass the NAME argument +$ typer main.py run Camila + +Hello Camila + +// It works! 🎉 +``` + +
+ +This is the simplest use case, not even using Typer internally, but it can already be quite useful for simple scripts. + +**Note**: auto-completion works when you create a Python package and run it with `--install-completion` or when you use the `typer` command. + +## Use Typer in your code + +Now let's start using Typer in your own code, update `main.py` with: + ```Python import typer @@ -80,9 +130,7 @@ if __name__ == "__main__": typer.run(main) ``` -### Run it - -Run your application: +Now you could run it with Python directly:
@@ -120,7 +168,7 @@ Hello Camila
-**Note**: auto-completion works when you create a Python package and run it with `--install-completion` or when you use Typer CLI. +**Note**: you can also call this same script with the `typer` command, but you don't need to. ## Example upgrade @@ -293,22 +341,43 @@ And similarly for **files**, **paths**, **enums** (choices), etc. And there are **You get**: great editor support, including **completion** and **type checks** everywhere. -**Your users get**: automatic **`--help`**, **auto-completion** in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using Typer CLI. +**Your users get**: automatic **`--help`**, **auto-completion** in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using the `typer` command. For a more complete example including more features, see the Tutorial - User Guide. -## Optional Dependencies +## Dependencies -Typer uses Click internally. That's the only dependency. +**Typer** stands on the shoulders of a giant. Its only internal required dependency is Click. -But you can also install extras: +By default it also comes with extra standard dependencies: -* rich: and Typer will show nicely formatted errors automatically. -* shellingham: and Typer will automatically detect the current shell when installing completion. +* rich: to show nicely formatted errors automatically. +* shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. +* `typer-cli`: adds the `typer` command to your shell: + * Quickly run scripts (that don't have to use Typer) with shell completion. + * Generate docs for your Typer applications. + +### `typer-slim` + +If you don't want the extra dependencies, install `typer-slim` instead. + +When you install with: + +```bash +pip install typer +``` + +...it's the equivalent of: + +```bash +pip install "typer-slim[standard]" +``` + +The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. -You can install `typer` with `rich` and `shellingham` with `pip install typer[all]`. +**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. ## License diff --git a/docs/features.md b/docs/features.md index dc41191173..f1fb6adef6 100644 --- a/docs/features.md +++ b/docs/features.md @@ -49,16 +49,16 @@ The resulting CLI apps created with **Typer** have the nice features of many "pr * Automatic completion for the CLI app in all operating systems, in all the shells (Bash, Zsh, Fish, PowerShell), so that the final user of your app can just hit TAB and get the available options or subcommands. * !!! note "* Auto completion" - Auto completion works when you create a package (installable with `pip`). Or when using [Typer CLI](typer-cli.md){.internal-link target=_blank}. + Auto completion works when you create a package (installable with `pip`). Or when using the `typer` command. - If you also add `shellingham` as a dependency, **Typer** will use it to auto-detect the current shell when installing completion. + **Typer** uses `shellingham` to auto-detect the current shell when installing completion. If you don't want to include `shellingham`, install `typer-slim`. **Typer** will automatically create 2 *CLI options*: * `--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 value with the name of the shell to install completion for, e.g.: + If you didn't add `shellingham` (if you installed `pip install typer-slim`) those *CLI options* take a value with the name of the shell to install completion for, e.g.: * `--install-completion bash`. * `--show-completion powershell`. @@ -74,7 +74,7 @@ The resulting CLI apps created with **Typer** have the nice features of many "pr Click is one of the most popular tools for building CLIs in Python. -**Typer** is based on it, so you get all its benefits, plug-ins, robustness, etc. +**Typer** is based on it, so you get all its benefits. But you can write simpler code with the benefits of modern Python. diff --git a/docs/index.md b/docs/index.md index 303774709f..0d4d824aa1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,6 +28,8 @@ Typer is a library for building CLI applications that users will **love using** and developers will **love creating**. Based on Python type hints. +It's also a command line tool to run scripts, automatically converting them to CLI applications. + The key features are: * **Intuitive to write**: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs. @@ -35,39 +37,87 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **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. +* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs - - -**Typer** is FastAPI's little sibling. - -And it's intended to be the FastAPI of CLIs. - -## Requirements - -**Typer** stands on the shoulders of a giant. Its only internal dependency is Click. +**Typer** is FastAPI's little sibling, it's the FastAPI of CLIs. ## Installation
```console -$ pip install "typer[all]" +$ pip install typer ---> 100% -Successfully installed typer +Successfully installed typer rich shellingham ```
-**Note**: that will include Rich. Rich is the recommended library to *display* information on the terminal, it is optional, but when installed, it's deeply integrated into **Typer** to display beautiful output. - ## Example ### The absolute minimum * Create a file `main.py` with: +```Python +def main(name: str): + print(f"Hello {name}") +``` + +This script doesn't even use Typer internally. But you can use the `typer` command to run it as a CLI application. + +### Run it + +Run your application with the `typer` command: + +
+ +```console +// Run your application +$ typer main.py run + +// You get a nice error, you are missing NAME +Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +Try 'typer [PATH_OR_MODULE] run --help' for help. +╭─ Error ───────────────────────────────────────────╮ +│ Missing argument 'NAME'. │ +╰───────────────────────────────────────────────────╯ + + +// You get a --help for free +$ typer main.py run --help + +Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME + +Run the provided Typer app. + +╭─ Arguments ───────────────────────────────────────╮ +│ * name TEXT [default: None] [required] | +╰───────────────────────────────────────────────────╯ +╭─ Options ─────────────────────────────────────────╮ +│ --help Show this message and exit. │ +╰───────────────────────────────────────────────────╯ + +// Now pass the NAME argument +$ typer main.py run Camila + +Hello Camila + +// It works! 🎉 +``` + +
+ +This is the simplest use case, not even using Typer internally, but it can already be quite useful for simple scripts. + +**Note**: auto-completion works when you create a Python package and run it with `--install-completion` or when you use the `typer` command. + +## Use Typer in your code + +Now let's start using Typer in your own code, update `main.py` with: + ```Python import typer @@ -80,9 +130,7 @@ if __name__ == "__main__": typer.run(main) ``` -### Run it - -Run your application: +Now you could run it with Python directly:
@@ -120,7 +168,7 @@ Hello Camila
-**Note**: auto-completion works when you create a Python package and run it with `--install-completion` or when you use Typer CLI. +**Note**: you can also call this same script with the `typer` command, but you don't need to. ## Example upgrade @@ -293,22 +341,43 @@ And similarly for **files**, **paths**, **enums** (choices), etc. And there are **You get**: great editor support, including **completion** and **type checks** everywhere. -**Your users get**: automatic **`--help`**, **auto-completion** in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using Typer CLI. +**Your users get**: automatic **`--help`**, **auto-completion** in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using the `typer` command. For a more complete example including more features, see the Tutorial - User Guide. -## Optional Dependencies +## Dependencies -Typer uses Click internally. That's the only dependency. +**Typer** stands on the shoulders of a giant. Its only internal required dependency is Click. -But you can also install extras: +By default it also comes with extra standard dependencies: -* rich: and Typer will show nicely formatted errors automatically. -* shellingham: and Typer will automatically detect the current shell when installing completion. +* rich: to show nicely formatted errors automatically. +* shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. +* `typer-cli`: adds the `typer` command to your shell: + * Quickly run scripts (that don't have to use Typer) with shell completion. + * Generate docs for your Typer applications. + +### `typer-slim` + +If you don't want the extra dependencies, install `typer-slim` instead. + +When you install with: + +```bash +pip install typer +``` + +...it's the equivalent of: + +```bash +pip install "typer-slim[standard]" +``` + +The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. -You can install `typer` with `rich` and `shellingham` with `pip install typer[all]`. +**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. ## License diff --git a/docs/tutorial/first-steps.md b/docs/tutorial/first-steps.md index 1f2371f0ab..6ef4212dde 100644 --- a/docs/tutorial/first-steps.md +++ b/docs/tutorial/first-steps.md @@ -452,11 +452,11 @@ And we'll use ***CLI option*** to refer to those *CLI parameters* that depend on We will use ***CLI parameter*** to refer to both, *CLI arguments* and *CLI options*. -## **Typer CLI** +## The `typer` Command -Now that you know the basics of **Typer**, you might want to install and use [Typer CLI](../typer-cli.md){.internal-link target=_blank}. +When you install `typer`, by default it adds a `typer` command to your shell. -**Typer CLI** is a tool to run your **Typer** scripts giving you ✨ auto completion ✨ in your terminal. +This `typer` command allows you to run your scripts with ✨ auto completion ✨ in your terminal. As an alternative to running with Python: @@ -470,7 +470,7 @@ Hello World -You can run with **Typer CLI**: +You can run with the `typer` command:
@@ -487,6 +487,6 @@ Hello World So you can use it to have auto completion for your own scripts as you continue with the tutorial. !!! tip - Your CLI application built with **Typer** won't need [Typer CLI](../typer-cli.md){.internal-link target=_blank} to have auto completion once you create a Python package. + Your CLI application built with **Typer** won't need the `typer` command to have auto completion once you create a Python package. But for short scripts and for learning, before creating a Python package, it might be useful. diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index 7937d570e4..6fb8075c87 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -61,18 +61,29 @@ You can learn a lot more by running some examples and playing around with them t ## Install **Typer** -The first step is to install **Typer**. - -For the tutorial, you might want to install it with all the optional dependencies and features: +The first step is to install **Typer**:
```console -$ pip install "typer[all]" +$ pip install typer ---> 100% -Successfully installed typer click shellingham rich +Successfully installed typer click shellingham rich typer-cli ```
-...that also includes `rich` and `shellingham`. +By default, `typer` comes with `rich`, `shellingham`, and `typer-cli`. + +!!! note + If you are an advanced user and want to opt out of these default extra dependencies, you can instead install `typer-slim`. + + ```bash + pip install typer + ``` + + ...is the equivalent of: + + ```bash + pip install "typer-slim[standard]" + ``` diff --git a/docs/tutorial/options-autocompletion.md b/docs/tutorial/options-autocompletion.md index a46c713172..7ac42dff8d 100644 --- a/docs/tutorial/options-autocompletion.md +++ b/docs/tutorial/options-autocompletion.md @@ -1,4 +1,4 @@ -As you have seen, apps built with **Typer** have completion in your shell that works when you create a Python package or using **Typer CLI**. +As you have seen, apps built with **Typer** have completion in your shell that works when you create a Python package or using the `typer` command. It normally completes *CLI options*, *CLI arguments*, and subcommands (that you will learn about later). @@ -8,9 +8,9 @@ But you can also provide auto completion for the **values** of *CLI options* and Before checking how to provide custom completions, let's check again how it works. -After installing completion (for your own Python package or for **Typer CLI**), when you use your CLI program and start adding a *CLI option* with `--` an then hit TAB, your shell will show you the available *CLI options* (the same for *CLI arguments*, etc). +After installing completion for your own Python package (or using the `typer` command), when you use your CLI program and start adding a *CLI option* with `--` an then hit TAB, your shell will show you the available *CLI options* (the same for *CLI arguments*, etc). -To check it quickly without creating a new Python package, install [Typer CLI](../typer-cli.md){.internal-link target=_blank}. +To check it quickly without creating a new Python package, use the `typer` command. Then let's create small example program: @@ -29,7 +29,7 @@ Then let's create small example program: {!> ../docs_src/options_autocompletion/tutorial001.py!} ``` -And let's try it with **Typer CLI** to get completion: +And let's try it with the `typer` command to get completion:
diff --git a/docs/tutorial/options/callback-and-context.md b/docs/tutorial/options/callback-and-context.md index 4c1c3a6527..4179eeff94 100644 --- a/docs/tutorial/options/callback-and-context.md +++ b/docs/tutorial/options/callback-and-context.md @@ -54,9 +54,9 @@ There's something to be aware of with callbacks and completion that requires som But first let's just use completion in your shell (Bash, Zsh, Fish, or PowerShell). -After installing completion (for your own Python package or for **Typer CLI**), when you use your CLI program and start adding a *CLI option* with `--` an then hit TAB, your shell will show you the available *CLI options* (the same for *CLI arguments*, etc). +After installing completion (for your own Python package), when you use your CLI program and start adding a *CLI option* with `--` an then hit TAB, your shell will show you the available *CLI options* (the same for *CLI arguments*, etc). -To check it quickly without creating a new Python package, install [Typer CLI](../../typer-cli.md){.internal-link target=_blank} and use it with the previous script: +To check it quickly with the previous script use the `typer` command:
diff --git a/docs/tutorial/package.md b/docs/tutorial/package.md index c26ff0087c..a6901a0a94 100644 --- a/docs/tutorial/package.md +++ b/docs/tutorial/package.md @@ -2,7 +2,7 @@ When you create a CLI program with **Typer** you probably want to create your ow That's what allows your users to install it and have it as an independent program that they can use in their terminal. -And that's also required for shell auto completion to work (unless you use your program through [Typer CLI](../typer-cli.md){.internal-link target=_blank}). +And that's also required for shell auto completion to work (unless you use your program through `typer` command). Nowadays, there are several ways and tools to create Python packages (what you install with `pip install something`). @@ -701,11 +701,9 @@ Loading portal gun
-## Generate docs with **Typer CLI** (optional) +## Generate docs -You can install and use [Typer CLI](../typer-cli.md){.internal-link target=_blank} to generate docs for your package. - -After installing it, you can use it to generate a new `README.md`: +You can use the `typer` command to generate docs for your package that you can put in your `README.md`:
@@ -721,6 +719,9 @@ You just have to pass it the module to import (`rick_portal_gun.main`) and it wi By specifying the `--name` of the program it will be able to use it while generating the docs. +!!! tip + If you installed `typer-slim` and don't have the `typer` command, you can use `python -m typer` instead. + ### Publish a new version with the docs Now you can publish a new version with the updated docs. diff --git a/docs/tutorial/printing.md b/docs/tutorial/printing.md index 120c0facbc..058998473e 100644 --- a/docs/tutorial/printing.md +++ b/docs/tutorial/printing.md @@ -18,27 +18,7 @@ Hello World ## Use Rich -You can also display beautiful and more complex information using Rich. - -### Install Rich - -First, you need to install it: - -
- -```console -// Rich comes with typer[all] -$ pip install "typer[all]" ----> 100% -Successfully installed typer rich - -// Alternatively, you can install Rich independently -$ pip install rich ----> 100% -Successfully installed rich -``` - -
+You can also display beautiful and more complex information using Rich. It comes by default when you install `typer`. ### Use Rich `print` diff --git a/docs/typer-cli.md b/docs/tutorial/typer-command.md similarity index 61% rename from docs/typer-cli.md rename to docs/tutorial/typer-command.md index 35f17e4d77..710115a749 100644 --- a/docs/typer-cli.md +++ b/docs/tutorial/typer-command.md @@ -1,100 +1,45 @@ -# Typer CLI +# `typer` command -

- Run Typer scripts with completion, without having to create a package, using Typer CLI. -

-

- - Build Status - - - Coverage - - - Package version - -

- -There is an optional utility tool called **Typer CLI**, additional to **Typer** itself. - -It's main feature is to provide ✨ completion ✨ in the Terminal for your own small programs built with **Typer**. - -...without you having to create a complete installable Python package. +The `typer` command provides ✨ completion ✨ in the Terminal for your own small scripts. Even if they don't use Typer internally. Of course, it works better if you use **Typer** in your script. It's probably most useful if you have a small custom Python script using **Typer** (maybe as part of some project), for some small tasks, and it's not complex/important enough to create a whole installable Python package for it (something to be installed with `pip`). -In that case, you can install **Typer CLI**, and run your program with the `typer` command in your Terminal, and it will provide completion for your script. - -You can also use **Typer CLI** to generate Markdown documentation for your own **Typer** programs 📝. - ---- - -**Documentation**: https://typer.tiangolo.com/typer-cli/ - -**Source Code for Typer CLI**: https://github.com/tiangolo/typer-cli - ---- - -## **Typer** or **Typer CLI** - -**Typer** is a library for building CLIs (Command Line Interface applications). - -You use **Typer** in your Python scripts. Like in: - -```Python -import typer +In that case, you can run your program with the `typer` command in your Terminal, and it will provide completion for your script. +The `typer` command also has functionality to generate Markdown documentation for your own **Typer** programs 📝. -def main(): - typer.echo("Hello World") +## Install +When you install **Typer** with: -if __name__ == "__main__": - typer.run(main) +```bash +pip install typer ``` -**Typer CLI** is a command line application to run simple programs created with **Typer**, with completion in your terminal 🚀. +...it includes the `typer` command. -You use **Typer CLI** in your terminal, to run your scripts (as an alternative to calling `python` directly). Like in: +If you don't want to have the `typer` command, you can install instead: -
- -```console -$ typer my_script.py run - -Hello World +```bash +pip install typer-slim ``` -
- -But you never import anything from **Typer CLI** in your own scripts. - -## Usage - -### Install +You can still use it by calling the Typer library as a module with: -Install **Typer CLI**: - -
- -```console -$ python -m pip install typer-cli ----> 100% -Successfully installed typer-cli +```bash +python -m typer ``` -
- -That creates a `typer` command you can call in your terminal, much like `python`, `git`, or `echo`. +## Install completion -You can then install completion for it: +You can then install completion for the `typer` command with:
```console $ typer --install-completion -zsh completion installed in /home/user/.bashrc. +bash completion installed in /home/user/.bashrc. Completion will take effect once you restart the terminal. ``` @@ -170,11 +115,9 @@ There's nothing wrong with using Python directly to run it. And, in fact, if som ⛔️ But in your terminal, you won't get completion when hitting TAB for any of the subcommands or options, like `hello`, `bye`, and `--name`. -### Run with **Typer CLI** - -Here's where **Typer CLI** is useful. +### Run with the `typer` command. -You can also run the same script with the `typer` command you get after installing `typer-cli`: +You can also run the same script with the `typer` command:
@@ -197,24 +140,24 @@ Bye Camila * Instead of using `python` directly you use the `typer` command. * After the name of the file, add the subcommand `run`. -✔️ If you installed completion for **Typer CLI** (for the `typer` command) as described above, when you hit TAB you will have ✨ completion for everything ✨, including all the subcommands and options of your script, like `hello`, `bye`, and `--name` 🚀. +✔️ If you installed completion for the `typer` command as described above, when you hit TAB you will have ✨ completion for everything ✨, including all the subcommands and options of your script, like `hello`, `bye`, and `--name` 🚀. ## If main -Because **Typer CLI** won't use the block with: +Because the `typer` command won't use the block with: ```Python if __name__ == "__main__": app() ``` -...you can also remove it if you are calling that script only with **Typer CLI** (using the `typer` command). +...you can also remove it if you are calling that script only with the `typer` command. ## Run other files -**Typer CLI** can run any script with **Typer**, but the script doesn't even have to use **Typer** at all. +The `typer` command can run any script with **Typer**, but the script doesn't even have to use **Typer** at all. -**Typer CLI** could even run a file with a function that could be used with `typer.run()`, even if the script doesn't use `typer.run()` or anything else. +You could even run a file with a function that could be used with `typer.run()`, even if the script doesn't use `typer.run()` or anything else. For example, a file `main.py` like this will still work: @@ -281,7 +224,7 @@ You can specify one of the following **CLI options**: ### Defaults -When your run a script with the **Typer CLI** (the `typer` command) it will use the app from the following priority: +When your run a script with the `typer` command it will use the app from the following priority: * An app object from the `--app` *CLI Option*. * A function to convert to a **Typer** app from `--func` *CLI Option* (like when using `typer.run()`). @@ -292,7 +235,7 @@ When your run a script with the **Typer CLI** (the `typer` command) it will use ## Generate docs -**Typer CLI** can also generate Markdown documentation for your **Typer** application. +You can also use the `typer` command to generate Markdown documentation for your **Typer** application. ### Sample script with docs @@ -302,9 +245,9 @@ For example, you could have a script like: {!../docs_src/commands/help/tutorial001.py!} ``` -### Generate docs with Typer CLI +### Generate docs with the `typer` command -Then you could generate docs for it with **Typer CLI**. +Then you could generate docs for it with the `typer` command. You can use the subcommand `utils`. @@ -318,6 +261,13 @@ $ typer some_script.py utils docs
+!!! tip + If you installed only `typer-slim` and you don't have the `typer` command, you can still generate docs with: + + ```console + $ python -m typer some_script.py utils docs + ``` + **Options**: * `--name TEXT`: The name of the CLI program to use in docs. @@ -425,9 +375,3 @@ $ awesome-cli init [OPTIONS] **Options**: * `--help`: Show this message and exit. - ---- - -## License - -**Typer CLI**, the same as **Typer**, is licensed under the terms of the MIT license. diff --git a/mkdocs.insiders.yml b/mkdocs.insiders.yml index 7c1870afb7..d0b5a56f6e 100644 --- a/mkdocs.insiders.yml +++ b/mkdocs.insiders.yml @@ -1,5 +1,4 @@ INHERIT: mkdocs.yml -plugins: - - search +# plugins: # TODO: Re-enable once this is fixed: https://github.com/squidfunk/mkdocs-material/issues/6983 # - social diff --git a/mkdocs.yml b/mkdocs.yml index 8022a19589..77024d83bb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,6 +16,11 @@ theme: repo_name: tiangolo/typer repo_url: https://github.com/tiangolo/typer edit_uri: "" +plugins: + search: null + redirects: + redirect_maps: + typer-cli.md: tutorial/typer-command.md nav: - Typer: index.md @@ -81,7 +86,7 @@ nav: - Using Click: tutorial/using-click.md - Building a Package: tutorial/package.md - tutorial/exceptions.md - - Typer CLI - completion for small scripts: typer-cli.md + - tutorial/typer-command.md - Alternatives, Inspiration and Comparisons: alternatives.md - Help Typer - Get Help: help-typer.md - Development - Contributing: contributing.md diff --git a/pyproject.toml b/pyproject.toml index 2ae5002fc8..f5abe95d3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,9 @@ requires = ["pdm-backend"] build-backend = "pdm.backend" [project] -name = "typer" +# pip install typer-slim: is only the Typer library, without extras +# pip install typer: is typer-slim[standard], with extras and typer-cli +name = "typer-slim" dynamic = ["version"] description = "Typer, build great CLIs. Easy to code. Based on Python type hints." authors = [ @@ -43,9 +45,12 @@ homepage = "https://github.com/tiangolo/typer" [project.optional-dependencies] all = [ - "colorama >=0.4.3,<0.5.0", - "shellingham >=1.3.0,<2.0.0", - "rich >=10.11.0,<14.0.0", + "shellingham >=1.3.0", + "rich >=10.11.0", +] +standard = [ + "shellingham >=1.3.0", + "rich >=10.11.0", ] [tool.pdm] diff --git a/tests/assets/cli/__init__.py b/tests/assets/cli/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/assets/cli/app_other_name.py b/tests/assets/cli/app_other_name.py new file mode 100644 index 0000000000..78bb101a90 --- /dev/null +++ b/tests/assets/cli/app_other_name.py @@ -0,0 +1,8 @@ +import typer + +application = typer.Typer() + + +@application.command() +def callback(name: str = "World"): + typer.echo(f"Hello {name}") diff --git a/tests/assets/cli/empty_script.py b/tests/assets/cli/empty_script.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/assets/cli/func_other_name.py b/tests/assets/cli/func_other_name.py new file mode 100644 index 0000000000..27a13823ef --- /dev/null +++ b/tests/assets/cli/func_other_name.py @@ -0,0 +1,2 @@ +def some_function(name: str = "World"): + print(f"Hello {name}") diff --git a/tests/assets/cli/multi_app.py b/tests/assets/cli/multi_app.py new file mode 100644 index 0000000000..1442aa2442 --- /dev/null +++ b/tests/assets/cli/multi_app.py @@ -0,0 +1,40 @@ +import typer + +sub_app = typer.Typer() + +variable = "Some text" + + +@sub_app.command() +def hello(name: str = "World", age: int = typer.Option(0, help="The age of the user")): + """ + Say Hello + """ + typer.echo(f"Hello {name}") + + +@sub_app.command() +def hi(user: str = typer.Argument("World", help="The name of the user to greet")): + """ + Say Hi + """ + + +@sub_app.command() +def bye(): + """ + Say bye + """ + typer.echo("sub bye") + + +app = typer.Typer(help="Demo App", epilog="The end") +app.add_typer(sub_app, name="sub") + + +@app.command() +def top(): + """ + Top command + """ + typer.echo("top") diff --git a/tests/assets/cli/multi_app_cli.py b/tests/assets/cli/multi_app_cli.py new file mode 100644 index 0000000000..0a73c7ebc3 --- /dev/null +++ b/tests/assets/cli/multi_app_cli.py @@ -0,0 +1,22 @@ +import typer + +sub_app = typer.Typer() + + +@sub_app.command() +def hello(): + typer.echo("sub hello") + + +@sub_app.command() +def bye(): + typer.echo("sub bye") + + +cli = typer.Typer() +cli.add_typer(sub_app, name="sub") + + +@cli.command() +def top(): + typer.echo("top") diff --git a/tests/assets/cli/multi_func.py b/tests/assets/cli/multi_func.py new file mode 100644 index 0000000000..c272ee2be1 --- /dev/null +++ b/tests/assets/cli/multi_func.py @@ -0,0 +1,12 @@ +message = "Stuff" + + +def say_stuff(): + print(message) + + +def main(name: str = "World"): + """ + Say hi to someone, by default to the World. + """ + print(f"Hello {name}") diff --git a/tests/assets/cli/multiapp-docs.md b/tests/assets/cli/multiapp-docs.md new file mode 100644 index 0000000000..ed4592f5c8 --- /dev/null +++ b/tests/assets/cli/multiapp-docs.md @@ -0,0 +1,102 @@ +# `multiapp` + +Demo App + +**Usage**: + +```console +$ multiapp [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--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. + +The end + +**Commands**: + +* `sub` +* `top`: Top command + +## `multiapp sub` + +**Usage**: + +```console +$ multiapp sub [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--help`: Show this message and exit. + +**Commands**: + +* `bye`: Say bye +* `hello`: Say Hello +* `hi`: Say Hi + +### `multiapp sub bye` + +Say bye + +**Usage**: + +```console +$ multiapp sub bye [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. + +### `multiapp sub hello` + +Say Hello + +**Usage**: + +```console +$ multiapp sub hello [OPTIONS] +``` + +**Options**: + +* `--name TEXT`: [default: World] +* `--age INTEGER`: The age of the user [default: 0] +* `--help`: Show this message and exit. + +### `multiapp sub hi` + +Say Hi + +**Usage**: + +```console +$ multiapp sub hi [OPTIONS] [USER] +``` + +**Arguments**: + +* `[USER]`: The name of the user to greet [default: World] + +**Options**: + +* `--help`: Show this message and exit. + +## `multiapp top` + +Top command + +**Usage**: + +```console +$ multiapp top [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. diff --git a/tests/assets/cli/not_python.txt b/tests/assets/cli/not_python.txt new file mode 100644 index 0000000000..5eb1a5ddd5 --- /dev/null +++ b/tests/assets/cli/not_python.txt @@ -0,0 +1 @@ +This is not Python diff --git a/tests/assets/cli/sample.py b/tests/assets/cli/sample.py new file mode 100644 index 0000000000..79ff29b5ac --- /dev/null +++ b/tests/assets/cli/sample.py @@ -0,0 +1,25 @@ +import typer + +app = typer.Typer() + + +@app.command() +def hello(name: str = "World", formal: bool = False): + """ + Say hi + """ + if formal: + typer.echo(f"Good morning Ms. {name}") + else: + typer.echo(f"Hello {name}!") + + +@app.command() +def bye(friend: bool = False): + """ + Say bye + """ + if friend: + typer.echo("Goodbye my friend") + else: + typer.echo("Goodbye") diff --git a/tests/test_cli/__init__.py b/tests/test_cli/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_cli/test_app_other_name.py b/tests/test_cli/test_app_other_name.py new file mode 100644 index 0000000000..2811c4376f --- /dev/null +++ b/tests/test_cli/test_app_other_name.py @@ -0,0 +1,41 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/app_other_name.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "--name" in result.stdout + + +def test_script(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/app_other_name.py", + "run", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello Camila" in result.stdout diff --git a/tests/test_cli/test_completion_run.py b/tests/test_cli/test_completion_run.py new file mode 100644 index 0000000000..20695b9339 --- /dev/null +++ b/tests/test_cli/test_completion_run.py @@ -0,0 +1,19 @@ +import os +import subprocess +import sys + + +def test_script_completion_run(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", "-m", "typer"], + capture_output=True, + encoding="utf-8", + env={ + **os.environ, + "___MAIN__.PY_COMPLETE": "complete_bash", + "_PYTHON _M TYPER_COMPLETE": "complete_bash", + "COMP_WORDS": "typer tests/assets/cli/sample.py", + "COMP_CWORD": "2", + }, + ) + assert "run" in result.stdout diff --git a/tests/test_cli/test_doc.py b/tests/test_cli/test_doc.py new file mode 100644 index 0000000000..903c51ddec --- /dev/null +++ b/tests/test_cli/test_doc.py @@ -0,0 +1,112 @@ +import subprocess +import sys +from pathlib import Path + + +def test_doc(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests.assets.cli.multi_app", + "utils", + "docs", + "--name", + "multiapp", + ], + capture_output=True, + encoding="utf-8", + ) + docs_path: Path = Path(__file__).parent.parent / "assets/cli/multiapp-docs.md" + docs = docs_path.read_text() + assert docs in result.stdout + assert "**Arguments**" in result.stdout + + +def test_doc_output(tmp_path: Path): + out_file: Path = tmp_path / "out.md" + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests.assets.cli.multi_app", + "utils", + "docs", + "--name", + "multiapp", + "--output", + str(out_file), + ], + capture_output=True, + encoding="utf-8", + ) + docs_path: Path = Path(__file__).parent.parent / "assets/cli/multiapp-docs.md" + docs = docs_path.read_text() + written_docs = out_file.read_text() + assert docs in written_docs + assert "Docs saved to:" in result.stdout + + +def test_doc_not_existing(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "no_typer", + "utils", + "docs", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Could not import as Python module:" in result.stderr + + +def test_doc_no_typer(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/empty_script.py", + "utils", + "docs", + ], + capture_output=True, + encoding="utf-8", + ) + assert "No Typer app found" in result.stderr + + +def test_doc_file_not_existing(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "assets/cli/not_existing.py", + "utils", + "docs", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Not a valid file or Python module:" in result.stderr diff --git a/tests/test_cli/test_empty_script.py b/tests/test_cli/test_empty_script.py new file mode 100644 index 0000000000..7e90789eb4 --- /dev/null +++ b/tests/test_cli/test_empty_script.py @@ -0,0 +1,20 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/empty_script.py", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "run" not in result.stdout diff --git a/tests/test_cli/test_func_other_name.py b/tests/test_cli/test_func_other_name.py new file mode 100644 index 0000000000..7949ff8f9b --- /dev/null +++ b/tests/test_cli/test_func_other_name.py @@ -0,0 +1,22 @@ +import subprocess +import sys + + +def test_script(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/func_other_name.py", + "run", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello Camila" in result.stdout diff --git a/tests/test_cli/test_help.py b/tests/test_cli/test_help.py new file mode 100644 index 0000000000..64e5495c9a --- /dev/null +++ b/tests/test_cli/test_help.py @@ -0,0 +1,38 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "run" in result.stdout + + +def test_not_python(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/not_python.txt", + "run", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Could not import as Python file" in result.stderr diff --git a/tests/test_cli/test_multi_app.py b/tests/test_cli/test_multi_app.py new file mode 100644 index 0000000000..5315289f5e --- /dev/null +++ b/tests/test_cli/test_multi_app.py @@ -0,0 +1,123 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "sub" in result.stdout + assert "top" in result.stdout + + +def test_script_app_non_existent(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--app", + "non_existent", + "tests/assets/cli/multi_app.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Not a Typer object:" in result.stderr + + +def test_script_sub(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app.py", + "run", + "sub", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "bye" in result.stdout + assert "hello" in result.stdout + + +def test_script_top(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app.py", + "run", + "top", + ], + capture_output=True, + encoding="utf-8", + ) + assert "top" in result.stdout + + +def test_script_sub_hello(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app.py", + "run", + "sub", + "hello", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello World" in result.stdout + + +def test_script_sub_bye(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app.py", + "run", + "sub", + "bye", + ], + capture_output=True, + encoding="utf-8", + ) + assert "sub bye" in result.stdout diff --git a/tests/test_cli/test_multi_app_cli.py b/tests/test_cli/test_multi_app_cli.py new file mode 100644 index 0000000000..1eaddaba87 --- /dev/null +++ b/tests/test_cli/test_multi_app_cli.py @@ -0,0 +1,102 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app_cli.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "sub" in result.stdout + assert "top" in result.stdout + + +def test_script_sub(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app_cli.py", + "run", + "sub", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "bye" in result.stdout + assert "hello" in result.stdout + + +def test_script_top(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app_cli.py", + "run", + "top", + ], + capture_output=True, + encoding="utf-8", + ) + assert "top" in result.stdout + + +def test_script_sub_hello(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app_cli.py", + "run", + "sub", + "hello", + ], + capture_output=True, + encoding="utf-8", + ) + assert "sub hello" in result.stdout + + +def test_script_sub_bye(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_app_cli.py", + "run", + "sub", + "bye", + ], + capture_output=True, + encoding="utf-8", + ) + assert "sub bye" in result.stdout diff --git a/tests/test_cli/test_multi_app_sub.py b/tests/test_cli/test_multi_app_sub.py new file mode 100644 index 0000000000..7d5f6f6888 --- /dev/null +++ b/tests/test_cli/test_multi_app_sub.py @@ -0,0 +1,46 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--app", + "sub_app", + "tests/assets/cli/multi_app.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "bye" in result.stdout + assert "hello" in result.stdout + assert "top" not in result.stdout + + +def test_script(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--app", + "sub_app", + "tests/assets/cli/multi_app.py", + "run", + "hello", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello World" in result.stdout diff --git a/tests/test_cli/test_multi_func.py b/tests/test_cli/test_multi_func.py new file mode 100644 index 0000000000..8b4b43a94d --- /dev/null +++ b/tests/test_cli/test_multi_func.py @@ -0,0 +1,106 @@ +import subprocess +import sys + + +def test_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_func.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Say hi to someone, by default to the World." in result.stdout + + +def test_script(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/multi_func.py", + "run", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello Camila" in result.stdout + + +def test_script_func_non_existent(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--func", + "non_existent", + "tests/assets/cli/multi_func.py", + "run", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Not a function:" in result.stderr + + +def test_script_func_not_function(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--func", + "message", + "tests/assets/cli/multi_func.py", + "run", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Not a function:" in result.stderr + + +def test_script_func(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "--func", + "say_stuff", + "tests/assets/cli/multi_func.py", + "run", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello" not in result.stdout + assert "Stuff" in result.stdout diff --git a/tests/test_cli/test_not_python.py b/tests/test_cli/test_not_python.py new file mode 100644 index 0000000000..00384d1f55 --- /dev/null +++ b/tests/test_cli/test_not_python.py @@ -0,0 +1,20 @@ +import subprocess +import sys + + +def test_not_python(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/not_python.txt", + "run", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Could not import as Python file" in result.stderr diff --git a/tests/test_cli/test_sub.py b/tests/test_cli/test_sub.py new file mode 100644 index 0000000000..6eb0d4dac4 --- /dev/null +++ b/tests/test_cli/test_sub.py @@ -0,0 +1,139 @@ +import subprocess +import sys + + +def test_script_hello(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "hello", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello World!" in result.stdout + + +def test_script_hello_name(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "hello", + "--name", + "Camila", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Hello Camila!" in result.stdout + + +def test_script_hello_name_formal(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "hello", + "--name", + "Camila", + "--formal", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Good morning Ms. Camila" in result.stdout + + +def test_script_bye(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "bye", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Goodbye" in result.stdout + + +def test_script_bye_friend(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "bye", + "--friend", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Goodbye my friend" in result.stdout + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "run" in result.stdout + + +def test_not_python(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/not_python.txt", + "run", + ], + capture_output=True, + encoding="utf-8", + ) + assert "Could not import as Python file" in result.stderr diff --git a/tests/test_cli/test_sub_completion.py b/tests/test_cli/test_sub_completion.py new file mode 100644 index 0000000000..0658883733 --- /dev/null +++ b/tests/test_cli/test_sub_completion.py @@ -0,0 +1,19 @@ +import os +import subprocess +import sys + + +def test_script_completion_run(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", "-m", "typer"], + capture_output=True, + encoding="utf-8", + env={ + **os.environ, + "___MAIN__.PY_COMPLETE": "complete_bash", + "_PYTHON _M TYPER_COMPLETE": "complete_bash", + "COMP_WORDS": "typer tests/assets/cli/sample.py run hello --", + "COMP_CWORD": "4", + }, + ) + assert "--name" in result.stdout diff --git a/tests/test_cli/test_sub_help.py b/tests/test_cli/test_sub_help.py new file mode 100644 index 0000000000..d59f56fb2c --- /dev/null +++ b/tests/test_cli/test_sub_help.py @@ -0,0 +1,24 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests/assets/cli/sample.py", + "run", + "--help", + ], + capture_output=True, + encoding="utf-8", + ) + assert "bye" in result.stdout + assert "Say bye" in result.stdout + assert "hello" in result.stdout + assert "Say hi" in result.stdout diff --git a/tests/test_cli/test_version.py b/tests/test_cli/test_version.py new file mode 100644 index 0000000000..18f4b00efe --- /dev/null +++ b/tests/test_cli/test_version.py @@ -0,0 +1,11 @@ +import subprocess +import sys + + +def test_script_help(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", "-m", "typer", "--version"], + capture_output=True, + encoding="utf-8", + ) + assert "Typer version:" in result.stdout diff --git a/tests/test_compat/test_option_get_help.py b/tests/test_compat/test_option_get_help.py index baca132cf0..362298b99a 100644 --- a/tests/test_compat/test_option_get_help.py +++ b/tests/test_compat/test_option_get_help.py @@ -48,7 +48,6 @@ def test_completion(): **os.environ, "_COMPAT_CLICK7_8.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "compat_click7_8.py --nickname ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Jonny" in result.stdout diff --git a/tests/test_completion/test_completion.py b/tests/test_completion/test_completion.py index 9f5dd426db..2af209e2dc 100644 --- a/tests/test_completion/test_completion.py +++ b/tests/test_completion/test_completion.py @@ -51,7 +51,6 @@ def test_completion_invalid_instruction(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "sourcebash", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert result.returncode != 0 @@ -66,7 +65,6 @@ def test_completion_source_bash(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_bash", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -83,7 +81,6 @@ def test_completion_source_invalid_shell(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_xxx", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Shell xxx not supported." in result.stderr @@ -97,7 +94,6 @@ def test_completion_source_invalid_instruction(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "explode_bash", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert 'Completion instruction "explode" not supported.' in result.stderr @@ -111,7 +107,6 @@ def test_completion_source_zsh(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_zsh", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "compdef _tutorial001py_completion tutorial001.py" in result.stdout @@ -125,7 +120,6 @@ def test_completion_source_fish(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_fish", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "complete --command tutorial001.py --no-files" in result.stdout @@ -139,7 +133,6 @@ def test_completion_source_powershell(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_powershell", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -156,7 +149,6 @@ def test_completion_source_pwsh(): env={ **os.environ, "_TUTORIAL001.PY_COMPLETE": "source_pwsh", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( diff --git a/tests/test_completion/test_completion_complete.py b/tests/test_completion/test_completion_complete.py index 359768f859..ea37f68546 100644 --- a/tests/test_completion/test_completion_complete.py +++ b/tests/test_completion/test_completion_complete.py @@ -15,7 +15,6 @@ def test_completion_complete_subcommand_bash(): "_TUTORIAL001.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial001.py del", "COMP_CWORD": "1", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "delete\ndelete-all" in result.stdout @@ -31,7 +30,6 @@ def test_completion_complete_subcommand_bash_invalid(): "_TUTORIAL001.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial001.py del", "COMP_CWORD": "42", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "create\ndelete\ndelete-all\ninit" in result.stdout @@ -46,7 +44,6 @@ def test_completion_complete_subcommand_zsh(): **os.environ, "_TUTORIAL001.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -64,7 +61,6 @@ def test_completion_complete_subcommand_zsh_files(): **os.environ, "_TUTORIAL001.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial001.py delete ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ("_files") in result.stdout @@ -80,7 +76,6 @@ def test_completion_complete_subcommand_fish(): "_TUTORIAL001.PY_COMPLETE": "complete_fish", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", "_TYPER_COMPLETE_FISH_ACTION": "get-args", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -99,7 +94,6 @@ def test_completion_complete_subcommand_fish_should_complete(): "_TUTORIAL001.PY_COMPLETE": "complete_fish", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", "_TYPER_COMPLETE_FISH_ACTION": "is-args", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert result.returncode == 0 @@ -115,7 +109,6 @@ def test_completion_complete_subcommand_fish_should_complete_no(): "_TUTORIAL001.PY_COMPLETE": "complete_fish", "_TYPER_COMPLETE_ARGS": "tutorial001.py delete ", "_TYPER_COMPLETE_FISH_ACTION": "is-args", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert result.returncode != 0 @@ -130,7 +123,6 @@ def test_completion_complete_subcommand_powershell(): **os.environ, "_TUTORIAL001.PY_COMPLETE": "complete_powershell", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -147,7 +139,6 @@ def test_completion_complete_subcommand_pwsh(): **os.environ, "_TUTORIAL001.PY_COMPLETE": "complete_pwsh", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ( @@ -164,7 +155,6 @@ def test_completion_complete_subcommand_noshell(): **os.environ, "_TUTORIAL001.PY_COMPLETE": "complete_noshell", "_TYPER_COMPLETE_ARGS": "tutorial001.py del", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ("") in result.stdout diff --git a/tests/test_completion/test_completion_complete_no_help.py b/tests/test_completion/test_completion_complete_no_help.py index c67c77a82b..4ac2bf98de 100644 --- a/tests/test_completion/test_completion_complete_no_help.py +++ b/tests/test_completion/test_completion_complete_no_help.py @@ -14,7 +14,6 @@ def test_completion_complete_subcommand_zsh(): **os.environ, "_TUTORIAL002.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial002.py ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "create" in result.stdout @@ -31,7 +30,6 @@ def test_completion_complete_subcommand_fish(): "_TUTORIAL002.PY_COMPLETE": "complete_fish", "_TYPER_COMPLETE_ARGS": "tutorial002.py ", "_TYPER_COMPLETE_FISH_ACTION": "get-args", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "create\ndelete" in result.stdout @@ -46,7 +44,6 @@ def test_completion_complete_subcommand_powershell(): **os.environ, "_TUTORIAL002.PY_COMPLETE": "complete_powershell", "_TYPER_COMPLETE_ARGS": "tutorial002.py ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ("create::: \ndelete::: ") in result.stdout @@ -61,7 +58,6 @@ def test_completion_complete_subcommand_pwsh(): **os.environ, "_TUTORIAL002.PY_COMPLETE": "complete_pwsh", "_TYPER_COMPLETE_ARGS": "tutorial002.py ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert ("create::: \ndelete::: ") in result.stdout diff --git a/tests/test_completion/test_completion_install.py b/tests/test_completion/test_completion_install.py index 7a3eac4a77..a6ad3c9f03 100644 --- a/tests/test_completion/test_completion_install.py +++ b/tests/test_completion/test_completion_install.py @@ -22,7 +22,6 @@ def test_completion_install_no_shell(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -48,7 +47,6 @@ def test_completion_install_bash(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -90,7 +88,6 @@ def test_completion_install_zsh(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -126,7 +123,6 @@ def test_completion_install_fish(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) diff --git a/tests/test_completion/test_completion_show.py b/tests/test_completion/test_completion_show.py index 5f94d50747..af4ed2a90e 100644 --- a/tests/test_completion/test_completion_show.py +++ b/tests/test_completion/test_completion_show.py @@ -21,7 +21,6 @@ def test_completion_show_no_shell(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -43,7 +42,6 @@ def test_completion_show_bash(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -68,7 +66,6 @@ def test_completion_source_zsh(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -90,7 +87,6 @@ def test_completion_source_fish(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -112,7 +108,6 @@ def test_completion_source_powershell(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) @@ -137,7 +132,6 @@ def test_completion_source_pwsh(): encoding="utf-8", env={ **os.environ, - "_TYPER_COMPLETE_TESTING": "True", "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True", }, ) diff --git a/tests/test_others.py b/tests/test_others.py index 367a8caeba..7986e1d7f0 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -151,7 +151,6 @@ def test_completion_untyped_parameters(): **os.environ, "_COMPLETION_NO_TYPES.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "completion_no_types.py --name Sebastian --name Ca", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "info name is: completion_no_types.py" in result.stderr @@ -178,7 +177,6 @@ def test_completion_untyped_parameters_different_order_correct_names(): **os.environ, "_COMPLETION_NO_TYPES_ORDER.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "completion_no_types_order.py --name Sebastian --name Ca", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "info name is: completion_no_types_order.py" in result.stderr diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial003.py b/tests/test_tutorial/test_options/test_callback/test_tutorial003.py index fe2ebd9d08..cbdaa8d094 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial003.py @@ -45,7 +45,6 @@ def test_completion(): "_TUTORIAL003.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial003.py --", "COMP_CWORD": "1", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--name" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py index cb2715f02e..a80dbcd2bd 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial003_an.py @@ -45,7 +45,6 @@ def test_completion(): "_TUTORIAL003_AN.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial003_an.py --", "COMP_CWORD": "1", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--name" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial004.py b/tests/test_tutorial/test_options/test_callback/test_tutorial004.py index 68b74448f7..70f9c1d399 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial004.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial004.py @@ -45,7 +45,6 @@ def test_completion(): "_TUTORIAL004.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial004.py --", "COMP_CWORD": "1", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--name" in result.stdout diff --git a/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py b/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py index b410fa7044..7756b202d6 100644 --- a/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py +++ b/tests/test_tutorial/test_options/test_callback/test_tutorial004_an.py @@ -45,7 +45,6 @@ def test_completion(): "_TUTORIAL004_AN.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial004_an.py --", "COMP_CWORD": "1", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--name" in result.stdout diff --git a/tests/test_tutorial/test_options/test_version/test_tutorial003.py b/tests/test_tutorial/test_options/test_version/test_tutorial003.py index 4287a5db0c..bcede6fc28 100644 --- a/tests/test_tutorial/test_options/test_version/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_version/test_tutorial003.py @@ -50,7 +50,6 @@ def test_completion(): "_TUTORIAL003.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial003.py --name Rick --v", "COMP_CWORD": "3", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--version" in result.stdout diff --git a/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py b/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py index 3081cb440f..5ccf2c922a 100644 --- a/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options/test_version/test_tutorial003_an.py @@ -50,7 +50,6 @@ def test_completion(): "_TUTORIAL003_AN.PY_COMPLETE": "complete_bash", "COMP_WORDS": "tutorial003_an.py --name Rick --v", "COMP_CWORD": "3", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "--version" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py index 49af214900..3e15fad9b6 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial002.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL002.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial002.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Camila" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py index 94f32fb21a..7db64bfa44 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial002_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL002_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial002_an.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Camila" in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py index 5870e445c3..ebd1e066ba 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial003.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL003.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial003.py --name Seb", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Camila" not in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py index 6583f9dccf..8f12583e80 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial003_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL003_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial003_an.py --name Seb", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert "Camila" not in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py index 1d7784ad2b..17c5f5197a 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial004.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL004.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial004_aux.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py index 30196732c6..dcfce0a4a7 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial004_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL004_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial004_an_aux.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py index bfa2aedb8a..b8ce1b1598 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial007.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL007.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial007.py --name Sebastian --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py index 6c8c294886..c35f23eb61 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial007_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL007_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial007_an.py --name Sebastian --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py index a347237e71..0874f23c5d 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL008.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial008.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py index ff5c25987c..cb2481a67c 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial008_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL008_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial008_an.py --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py index 8d9a73e755..3c7eb0cc64 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL009.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial009.py --name Sebastian --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py index fd4b65f1f1..56182ac3b9 100644 --- a/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py +++ b/tests/test_tutorial/test_options_autocompletion/test_tutorial009_an.py @@ -18,7 +18,6 @@ def test_completion(): **os.environ, "_TUTORIAL009_AN.PY_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": "tutorial009_an.py --name Sebastian --name ", - "_TYPER_COMPLETE_TESTING": "True", }, ) assert '"Camila":"The reader of books."' in result.stdout diff --git a/typer/__init__.py b/typer/__init__.py index a659d767b6..0d3a4bbfa9 100644 --- a/typer/__init__.py +++ b/typer/__init__.py @@ -1,6 +1,6 @@ """Typer, build great CLIs. Easy to code. Based on Python type hints.""" -__version__ = "0.11.1" +__version__ = "0.12.dev2" from shutil import get_terminal_size as get_terminal_size diff --git a/typer/__main__.py b/typer/__main__.py new file mode 100644 index 0000000000..4e28416e10 --- /dev/null +++ b/typer/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/typer/cli.py b/typer/cli.py new file mode 100644 index 0000000000..12a755de48 --- /dev/null +++ b/typer/cli.py @@ -0,0 +1,292 @@ +import importlib.util +import re +import sys +from pathlib import Path +from typing import Any, List, Optional + +import click +import typer +import typer.core +from click import Command, Group, Option + +from . import __version__ + +default_app_names = ("app", "cli", "main") +default_func_names = ("main", "cli", "app") + +app = typer.Typer() +utils_app = typer.Typer(help="Extra utility commands for Typer apps.") +app.add_typer(utils_app, name="utils") + + +class State: + def __init__(self) -> None: + self.app: Optional[str] = None + self.func: Optional[str] = None + self.file: Optional[Path] = None + self.module: Optional[str] = None + + +state = State() + + +def maybe_update_state(ctx: click.Context) -> None: + path_or_module = ctx.params.get("path_or_module") + if path_or_module: + file_path = Path(path_or_module) + if file_path.exists() and file_path.is_file(): + state.file = file_path + else: + if not re.fullmatch(r"[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)*", path_or_module): + typer.echo( + f"Not a valid file or Python module: {path_or_module}", err=True + ) + sys.exit(1) + state.module = path_or_module + app_name = ctx.params.get("app") + if app_name: + state.app = app_name + func_name = ctx.params.get("func") + if func_name: + state.func = func_name + + +class TyperCLIGroup(typer.core.TyperGroup): + def list_commands(self, ctx: click.Context) -> List[str]: + self.maybe_add_run(ctx) + return super().list_commands(ctx) + + def get_command(self, ctx: click.Context, name: str) -> Optional[Command]: + self.maybe_add_run(ctx) + return super().get_command(ctx, name) + + def invoke(self, ctx: click.Context) -> Any: + self.maybe_add_run(ctx) + return super().invoke(ctx) + + def maybe_add_run(self, ctx: click.Context) -> None: + maybe_update_state(ctx) + maybe_add_run_to_cli(self) + + +def get_typer_from_module(module: Any) -> Optional[typer.Typer]: + # Try to get defined app + if state.app: + obj = getattr(module, state.app, None) + if not isinstance(obj, typer.Typer): + typer.echo(f"Not a Typer object: --app {state.app}", err=True) + sys.exit(1) + return obj + # Try to get defined function + if state.func: + func_obj = getattr(module, state.func, None) + if not callable(func_obj): + typer.echo(f"Not a function: --func {state.func}", err=True) + sys.exit(1) + sub_app = typer.Typer() + sub_app.command()(func_obj) + return sub_app + # Iterate and get a default object to use as CLI + local_names = dir(module) + local_names_set = set(local_names) + # Try to get a default Typer app + for name in default_app_names: + if name in local_names_set: + obj = getattr(module, name, None) + if isinstance(obj, typer.Typer): + return obj + # Try to get any Typer app + for name in local_names_set - set(default_app_names): + obj = getattr(module, name) + if isinstance(obj, typer.Typer): + return obj + # Try to get a default function + for func_name in default_func_names: + func_obj = getattr(module, func_name, None) + if callable(func_obj): + sub_app = typer.Typer() + sub_app.command()(func_obj) + return sub_app + # Try to get any func app + for func_name in local_names_set - set(default_func_names): + func_obj = getattr(module, func_name) + if callable(func_obj): + sub_app = typer.Typer() + sub_app.command()(func_obj) + return sub_app + return None + + +def get_typer_from_state() -> Optional[typer.Typer]: + spec = None + if state.file: + module_name = state.file.name + spec = importlib.util.spec_from_file_location(module_name, str(state.file)) + elif state.module: + spec = importlib.util.find_spec(state.module) + if spec is None: + if state.file: + typer.echo(f"Could not import as Python file: {state.file}", err=True) + else: + typer.echo(f"Could not import as Python module: {state.module}", err=True) + sys.exit(1) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) # type: ignore + obj = get_typer_from_module(module) + return obj + + +def maybe_add_run_to_cli(cli: click.Group) -> None: + if "run" not in cli.commands: + if state.file or state.module: + obj = get_typer_from_state() + if obj: + obj._add_completion = False + click_obj = typer.main.get_command(obj) + click_obj.name = "run" + if not click_obj.help: + click_obj.help = "Run the provided Typer app." + cli.add_command(click_obj) + + +def print_version(ctx: click.Context, param: Option, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + typer.echo(f"Typer version: {__version__}") + raise typer.Exit() + + +@app.callback(cls=TyperCLIGroup, no_args_is_help=True) +def callback( + ctx: typer.Context, + *, + path_or_module: str = typer.Argument(None), + app: str = typer.Option(None, help="The typer app object/variable to use."), + func: str = typer.Option(None, help="The function to convert to Typer."), + version: bool = typer.Option( + False, + "--version", + help="Print version and exit.", + callback=print_version, + ), +) -> None: + """ + Run Typer scripts with completion, without having to create a package. + + You probably want to install completion for the typer command: + + $ typer --install-completion + + https://typer.tiangolo.com/ + """ + maybe_update_state(ctx) + + +def get_docs_for_click( + *, + obj: Command, + ctx: typer.Context, + indent: int = 0, + name: str = "", + call_prefix: str = "", +) -> str: + docs = "#" * (1 + indent) + command_name = name or obj.name + if call_prefix: + command_name = f"{call_prefix} {command_name}" + title = f"`{command_name}`" if command_name else "CLI" + docs += f" {title}\n\n" + if obj.help: + docs += f"{obj.help}\n\n" + usage_pieces = obj.collect_usage_pieces(ctx) + if usage_pieces: + docs += "**Usage**:\n\n" + docs += "```console\n" + docs += "$ " + if command_name: + docs += f"{command_name} " + docs += f"{' '.join(usage_pieces)}\n" + docs += "```\n\n" + args = [] + opts = [] + for param in obj.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + if param.param_type_name == "argument": + args.append(rv) + elif param.param_type_name == "option": + opts.append(rv) + if args: + docs += "**Arguments**:\n\n" + for arg_name, arg_help in args: + docs += f"* `{arg_name}`" + if arg_help: + docs += f": {arg_help}" + docs += "\n" + docs += "\n" + if opts: + docs += "**Options**:\n\n" + for opt_name, opt_help in opts: + docs += f"* `{opt_name}`" + if opt_help: + docs += f": {opt_help}" + docs += "\n" + docs += "\n" + if obj.epilog: + docs += f"{obj.epilog}\n\n" + if isinstance(obj, Group): + group = obj + commands = group.list_commands(ctx) + if commands: + docs += "**Commands**:\n\n" + for command in commands: + command_obj = group.get_command(ctx, command) + assert command_obj + docs += f"* `{command_obj.name}`" + command_help = command_obj.get_short_help_str() + if command_help: + docs += f": {command_help}" + docs += "\n" + docs += "\n" + for command in commands: + command_obj = group.get_command(ctx, command) + assert command_obj + use_prefix = "" + if command_name: + use_prefix += f"{command_name}" + docs += get_docs_for_click( + obj=command_obj, ctx=ctx, indent=indent + 1, call_prefix=use_prefix + ) + return docs + + +@utils_app.command() +def docs( + ctx: typer.Context, + name: str = typer.Option("", help="The name of the CLI program to use in docs."), + output: Path = typer.Option( + None, + help="An output file to write docs to, like README.md.", + file_okay=True, + dir_okay=False, + ), +) -> None: + """ + Generate Markdown docs for a Typer app. + """ + typer_obj = get_typer_from_state() + if not typer_obj: + typer.echo("No Typer app found", err=True) + raise typer.Abort() + click_obj = typer.main.get_command(typer_obj) + docs = get_docs_for_click(obj=click_obj, ctx=ctx, name=name) + clean_docs = f"{docs.strip()}\n" + if output: + output.write_text(clean_docs) + typer.echo(f"Docs saved to: {output}") + else: + typer.echo(clean_docs) + + +def main() -> Any: + return app() diff --git a/typer_cli_package/README.md b/typer_cli_package/README.md new file mode 100644 index 0000000000..dba1a0dcf7 --- /dev/null +++ b/typer_cli_package/README.md @@ -0,0 +1,49 @@ +

+ Typer +

+

+ Typer, build great CLIs. Easy to code. Based on Python type hints. +

+

+ + Test + + + Publish + + + Coverage + + Package version + +

+ +--- + +**Documentation**: https://typer.tiangolo.com/tutorial/typer-command/ + +**Source Code**: https://github.com/tiangolo/typer + +--- + +Typer is a library for building CLI applications that users will **love using** and developers will **love creating**. Based on Python type hints. + +## Typer CLI + +This package, `typer-cli`, only provides a command `typer` in the shell with the same functionality of `python -m typer`. + +The only reason why this is a separate package is to allow developers to opt out of the `typer` command by installing `typer-slim`, that doesn't include `typer-cli`. + +You probably **should not** install this package. + +Install instead: + +```bash +pip install typer +``` + +That includes this package, `typer-cli`, with the `typer` command. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/typer_cli_package/pdm_build.py b/typer_cli_package/pdm_build.py new file mode 100644 index 0000000000..cca6d59a75 --- /dev/null +++ b/typer_cli_package/pdm_build.py @@ -0,0 +1,40 @@ +from pathlib import Path +from typing import List + +from pdm.backend.hooks import Context + +packages_to_sync = ["typer-slim"] + +license_name = "LICENSE" +license_path = Path("..") / license_name + + +def pdm_build_hook_enabled(context: Context): + return context.target == "sdist" + + +def pdm_build_initialize(context: Context): + metadata = context.config.metadata + # Get main version + version = metadata["version"] + # Update version in dependencies to sync them + dependencies: List[str] = metadata["dependencies"] + new_dependencies = [] + for dep in dependencies: + if any(dep.startswith(name) for name in packages_to_sync): + new_dep = f"{dep}=={version}" + new_dependencies.append(new_dep) + else: + new_dependencies.append(dep) + if new_dependencies != dependencies: + metadata["dependencies"] = new_dependencies + # LICENSE + license_content = license_path.read_text() + context.ensure_build_dir() + # # Workaround, copy LICENSE to package_dir during build + Path(license_name).write_text(license_content) + + +def pdm_build_finalize(context: Context, artifact: Path): + # Workaround, remove LICENSE from package_dir after build + Path(license_name).unlink() diff --git a/typer_cli_package/pyproject.toml b/typer_cli_package/pyproject.toml new file mode 100644 index 0000000000..2bb4f8d26c --- /dev/null +++ b/typer_cli_package/pyproject.toml @@ -0,0 +1,55 @@ +[build-system] +requires = ["pdm-backend"] +build-backend = "pdm.backend" + +[project] +name = "typer-cli" +dynamic = ["version"] +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +authors = [ + {name = "Sebastián Ramírez", email = "tiangolo@gmail.com"}, +] +readme = "README.md" +requires-python = ">=3.7" +classifiers = [ + "Intended Audience :: Information Technology", + "Intended Audience :: System Administrators", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development", + "Typing :: Typed", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "License :: OSI Approved :: MIT License", +] +dependencies = [ + "typer-slim[standard]", +] + +[project.urls] +Documentation = "https://typer.tiangolo.com/" +homepage = "https://github.com/tiangolo/typer" + +[project.optional-dependencies] +# For backwards compatibility +all = [] + +[project.scripts] +typer = "typer.cli:main" + +[tool.pdm] +version = { source = "file", path = "../typer/__init__.py" } +distribution = true + +[tool.pdm.build] +excludes = ["*"] diff --git a/typer_package/pdm_build.py b/typer_package/pdm_build.py new file mode 100644 index 0000000000..b670aa9504 --- /dev/null +++ b/typer_package/pdm_build.py @@ -0,0 +1,49 @@ +from pathlib import Path +from typing import List + +from pdm.backend.hooks import Context + +packages_to_sync = ["typer-slim", "typer-cli"] + +readme_name = "README.md" +license_name = "LICENSE" +readme_path = Path("..") / readme_name +license_path = Path("..") / license_name + + +def pdm_build_hook_enabled(context: Context): + return context.target == "sdist" + + +def pdm_build_initialize(context: Context): + metadata = context.config.metadata + # Get main version + version = metadata["version"] + # Update version in dependencies to sync them + dependencies: List[str] = metadata["dependencies"] + new_dependencies = [] + for dep in dependencies: + if any(dep.startswith(name) for name in packages_to_sync): + new_dep = f"{dep}=={version}" + new_dependencies.append(new_dep) + else: + new_dependencies.append(dep) + if new_dependencies != dependencies: + metadata["dependencies"] = new_dependencies + # README.md and LICENSE + readme_content = readme_path.read_text() + license_content = license_path.read_text() + metadata["readme"] = readme_name + context.ensure_build_dir() + # Copy README.md and LICENSE to build directory + # (context.build_dir / readme_name).write_text(readme_content) + # (context.build_dir / license_name).write_text(license_content) + # # Workaround, copy README.md and LICENSE to package_dir during build + Path(readme_name).write_text(readme_content) + Path(license_name).write_text(license_content) + + +def pdm_build_finalize(context: Context, artifact: Path): + # Workaround, remove README.md and LICENSE from package_dir after build + Path(readme_name).unlink() + Path(license_name).unlink() diff --git a/typer_package/pyproject.toml b/typer_package/pyproject.toml new file mode 100644 index 0000000000..c2f3f45bfa --- /dev/null +++ b/typer_package/pyproject.toml @@ -0,0 +1,52 @@ +[build-system] +requires = ["pdm-backend"] +build-backend = "pdm.backend" + +[project] +name = "typer" +dynamic = ["version"] +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +authors = [ + {name = "Sebastián Ramírez", email = "tiangolo@gmail.com"}, +] +requires-python = ">=3.7" +classifiers = [ + "Intended Audience :: Information Technology", + "Intended Audience :: System Administrators", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development", + "Typing :: Typed", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "License :: OSI Approved :: MIT License", +] +dependencies = [ + "typer-slim[standard]", + "typer-cli", +] + +[project.urls] +Documentation = "https://typer.tiangolo.com/" +homepage = "https://github.com/tiangolo/typer" + +[project.optional-dependencies] +# For backwards compatibility +all = [] + +[tool.pdm] +version = { source = "file", path = "../typer/__init__.py" } +distribution = true + +[tool.pdm.build] +excludes = ["*"] From 8b02247c937643504a0025a94abc2a0d3a8d0136 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 30 Mar 2024 02:09:23 +0000 Subject: [PATCH 28/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 48ed28ad12..1e6c174eda 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,9 @@ ## Latest Changes +### Features + +* ✨ Add `typer-slim` package without extras, make `typer` include `typer-slim[default]` and integrate Typer CLI (`typer` command) into Typer. PR [#780](https://github.com/tiangolo/typer/pull/780) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 🔧 Temporarily disable social plugin while a MkDocs issue is handled. PR [#779](https://github.com/tiangolo/typer/pull/779) by [@tiangolo](https://github.com/tiangolo). From ef9beaf521047d44b0588f9f6927aa128d6b3f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 29 Mar 2024 21:19:27 -0500 Subject: [PATCH 29/37] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 2 ++ typer/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index 1e6c174eda..73cc8a1f7d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,7 @@ ## Latest Changes +## 0.12.0 + ### Features * ✨ Add `typer-slim` package without extras, make `typer` include `typer-slim[default]` and integrate Typer CLI (`typer` command) into Typer. PR [#780](https://github.com/tiangolo/typer/pull/780) by [@tiangolo](https://github.com/tiangolo). diff --git a/typer/__init__.py b/typer/__init__.py index 0d3a4bbfa9..4fa2de27f2 100644 --- a/typer/__init__.py +++ b/typer/__init__.py @@ -1,6 +1,6 @@ """Typer, build great CLIs. Easy to code. Based on Python type hints.""" -__version__ = "0.12.dev2" +__version__ = "0.12.0" from shutil import get_terminal_size as get_terminal_size From bdaa5c69467249daf2a2ee324aab942e54bbc715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 30 Mar 2024 19:17:15 -0500 Subject: [PATCH 30/37] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20`typer?= =?UTF-8?q?=20./someprogram.py=20utils=20docs=20--title`=20(#782)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jeffrey Newman --- docs/tutorial/typer-command.md | 1 + tests/assets/cli/multiapp-docs-title.md | 102 ++++++++++++++++++++++++ tests/test_cli/test_doc.py | 30 +++++++ typer/cli.py | 13 ++- 4 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 tests/assets/cli/multiapp-docs-title.md diff --git a/docs/tutorial/typer-command.md b/docs/tutorial/typer-command.md index 710115a749..021dee002d 100644 --- a/docs/tutorial/typer-command.md +++ b/docs/tutorial/typer-command.md @@ -272,6 +272,7 @@ $ typer some_script.py utils docs * `--name TEXT`: The name of the CLI program to use in docs. * `--output FILE`: An output file to write docs to, like README.md. +* `--title TEXT`: A title to use in the docs, by default the name of the command. For example: diff --git a/tests/assets/cli/multiapp-docs-title.md b/tests/assets/cli/multiapp-docs-title.md new file mode 100644 index 0000000000..e688a9ba91 --- /dev/null +++ b/tests/assets/cli/multiapp-docs-title.md @@ -0,0 +1,102 @@ +# Awesome CLI + +Demo App + +**Usage**: + +```console +$ multiapp [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--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. + +The end + +**Commands**: + +* `sub` +* `top`: Top command + +## `multiapp sub` + +**Usage**: + +```console +$ multiapp sub [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--help`: Show this message and exit. + +**Commands**: + +* `bye`: Say bye +* `hello`: Say Hello +* `hi`: Say Hi + +### `multiapp sub bye` + +Say bye + +**Usage**: + +```console +$ multiapp sub bye [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. + +### `multiapp sub hello` + +Say Hello + +**Usage**: + +```console +$ multiapp sub hello [OPTIONS] +``` + +**Options**: + +* `--name TEXT`: [default: World] +* `--age INTEGER`: The age of the user [default: 0] +* `--help`: Show this message and exit. + +### `multiapp sub hi` + +Say Hi + +**Usage**: + +```console +$ multiapp sub hi [OPTIONS] [USER] +``` + +**Arguments**: + +* `[USER]`: The name of the user to greet [default: World] + +**Options**: + +* `--help`: Show this message and exit. + +## `multiapp top` + +Top command + +**Usage**: + +```console +$ multiapp top [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. diff --git a/tests/test_cli/test_doc.py b/tests/test_cli/test_doc.py index 903c51ddec..98e30631ba 100644 --- a/tests/test_cli/test_doc.py +++ b/tests/test_cli/test_doc.py @@ -55,6 +55,36 @@ def test_doc_output(tmp_path: Path): assert "Docs saved to:" in result.stdout +def test_doc_title_output(tmp_path: Path): + out_file: Path = tmp_path / "out.md" + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests.assets.cli.multi_app", + "utils", + "docs", + "--name", + "multiapp", + "--title", + "Awesome CLI", + "--output", + str(out_file), + ], + capture_output=True, + encoding="utf-8", + ) + docs_path: Path = Path(__file__).parent.parent / "assets/cli/multiapp-docs-title.md" + docs = docs_path.read_text() + written_docs = out_file.read_text() + assert docs in written_docs + assert "Docs saved to:" in result.stdout + + def test_doc_not_existing(): result = subprocess.run( [ diff --git a/typer/cli.py b/typer/cli.py index 12a755de48..70b9101f37 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -189,12 +189,14 @@ def get_docs_for_click( indent: int = 0, name: str = "", call_prefix: str = "", + title: Optional[str] = None, ) -> str: docs = "#" * (1 + indent) command_name = name or obj.name if call_prefix: command_name = f"{call_prefix} {command_name}" - title = f"`{command_name}`" if command_name else "CLI" + if not title: + title = f"`{command_name}`" if command_name else "CLI" docs += f" {title}\n\n" if obj.help: docs += f"{obj.help}\n\n" @@ -264,12 +266,17 @@ def get_docs_for_click( def docs( ctx: typer.Context, name: str = typer.Option("", help="The name of the CLI program to use in docs."), - output: Path = typer.Option( + output: Optional[Path] = typer.Option( None, help="An output file to write docs to, like README.md.", file_okay=True, dir_okay=False, ), + title: Optional[str] = typer.Option( + None, + help="The title for the documentation page. If not provided, the name of " + "the program is used.", + ), ) -> None: """ Generate Markdown docs for a Typer app. @@ -279,7 +286,7 @@ def docs( typer.echo("No Typer app found", err=True) raise typer.Abort() click_obj = typer.main.get_command(typer_obj) - docs = get_docs_for_click(obj=click_obj, ctx=ctx, name=name) + docs = get_docs_for_click(obj=click_obj, ctx=ctx, name=name, title=title) clean_docs = f"{docs.strip()}\n" if output: output.write_text(clean_docs) From 968d81df54997fa0219ca2de2aeacbab54daa003 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 31 Mar 2024 00:47:50 +0000 Subject: [PATCH 31/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 73cc8a1f7d..9b675691f1 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,9 @@ ## Latest Changes +### Features + +* ✨ Add support for `typer ./someprogram.py utils docs --title`. PR [#782](https://github.com/tiangolo/typer/pull/782) by [@tiangolo](https://github.com/tiangolo). + ## 0.12.0 ### Features From 2a19c0c1d52669e03282e63eb35b09a9cddc73d4 Mon Sep 17 00:00:00 2001 From: Esteban Maya Date: Mon, 1 Apr 2024 20:59:38 -0500 Subject: [PATCH 32/37] =?UTF-8?q?=F0=9F=91=B7=20Add=20cron=20to=20run=20te?= =?UTF-8?q?st=20once=20a=20week=20on=20monday=20(#783)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6cef6278ca..61d114c611 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,9 @@ on: types: - opened - synchronize + schedule: + # cron every week on monday + - cron: "0 0 * * 1" jobs: test: From 8bac8213aab544442b4f59ecc5eac45f4c208c63 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 2 Apr 2024 01:59:54 +0000 Subject: [PATCH 33/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 9b675691f1..733c50c3e7 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,10 @@ * ✨ Add support for `typer ./someprogram.py utils docs --title`. PR [#782](https://github.com/tiangolo/typer/pull/782) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* 👷 Add cron to run test once a week on monday. PR [#783](https://github.com/tiangolo/typer/pull/783) by [@estebanx64](https://github.com/estebanx64). + ## 0.12.0 ### Features From 05ffb24386cfa6cd23fa5f18b9eb233cd363e309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 5 Apr 2024 04:29:30 +0400 Subject: [PATCH 34/37] =?UTF-8?q?=F0=9F=90=9B=20Fix=20broken=20installatio?= =?UTF-8?q?n=20when=20upgrading=20from=20`typer=20<0.12.0`=20to=20`typer?= =?UTF-8?q?=20>=3D0.12.0`,=20make=20`typer`=20independent=20of=20`typer-sl?= =?UTF-8?q?im`,=20include=20`typer`=20command=20in=20`typer`=20package=20(?= =?UTF-8?q?#791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish.yml | 7 +-- .github/workflows/test-redistribute.yml | 11 ++--- README.md | 13 ++--- docs/index.md | 13 ++--- docs/tutorial/index.md | 6 +-- pdm_build.py | 55 ++++++++++++++++++++++ pyproject.toml | 55 ++++++++++++++++++---- {typer_cli_package => typer-cli}/README.md | 10 ++-- typer/__init__.py | 2 +- typer_cli_package/pdm_build.py | 40 ---------------- typer_cli_package/pyproject.toml | 55 ---------------------- typer_package/pdm_build.py | 49 ------------------- typer_package/pyproject.toml | 52 -------------------- 13 files changed, 128 insertions(+), 240 deletions(-) create mode 100644 pdm_build.py rename {typer_cli_package => typer-cli}/README.md (82%) delete mode 100644 typer_cli_package/pdm_build.py delete mode 100644 typer_cli_package/pyproject.toml delete mode 100644 typer_package/pdm_build.py delete mode 100644 typer_package/pyproject.toml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1a842c4ea7..80cae43a7f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,8 +14,6 @@ jobs: - typer-slim - typer - typer-cli - env: - dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} permissions: id-token: write steps: @@ -34,9 +32,8 @@ jobs: - name: Install build dependencies run: pip install build - name: Build distribution - working-directory: ${{ env.dir }} + env: + TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} run: python -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.8.11 - with: - packages-dir: ${{ env.dir }}/dist/ diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index c16d19d7b4..d2a33d30e2 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -18,8 +18,6 @@ jobs: - typer-slim - typer - typer-cli - env: - dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} steps: - name: Dump GitHub context env: @@ -36,25 +34,24 @@ jobs: - name: Install build dependencies run: pip install build - name: Build source distribution - working-directory: ${{ env.dir }} + env: + TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} run: python -m build --sdist - name: Decompress source distribution - working-directory: ${{ env.dir }} run: | cd dist tar xvf typer*.tar.gz - name: Install test dependencies - if: ${{ matrix.package == 'typer-slim' }} + if: ${{ matrix.package != 'typer-cli' }} run: | cd dist/typer*/ pip install -r requirements-tests.txt - name: Run source distribution tests - if: ${{ matrix.package == 'typer-slim' }} + if: ${{ matrix.package != 'typer-cli' }} run: | cd dist/typer*/ bash scripts/test.sh - name: Build wheel distribution - working-directory: ${{ env.dir }} run: | cd dist pip wheel --no-deps typer*.tar.gz diff --git a/README.md b/README.md index 0d4d824aa1..6bb4983a9f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **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. -* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. +* **Run scripts**: Typer includes a `typer` command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs @@ -355,13 +355,10 @@ By default it also comes with extra standard dependencies: * shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. -* `typer-cli`: adds the `typer` command to your shell: - * Quickly run scripts (that don't have to use Typer) with shell completion. - * Generate docs for your Typer applications. ### `typer-slim` -If you don't want the extra dependencies, install `typer-slim` instead. +If you don't want the extra standard optional dependencies, install `typer-slim` instead. When you install with: @@ -369,15 +366,15 @@ When you install with: pip install typer ``` -...it's the equivalent of: +...it includes the same code and dependencies as: ```bash pip install "typer-slim[standard]" ``` -The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. +The `standard` extra dependencies are `rich` and `shellingham`. -**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. +**Note**: The `typer` command is only included in the `typer` package. ## License diff --git a/docs/index.md b/docs/index.md index 0d4d824aa1..6bb4983a9f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,7 +37,7 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **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. -* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. +* **Run scripts**: Typer includes a `typer` command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs @@ -355,13 +355,10 @@ By default it also comes with extra standard dependencies: * shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. -* `typer-cli`: adds the `typer` command to your shell: - * Quickly run scripts (that don't have to use Typer) with shell completion. - * Generate docs for your Typer applications. ### `typer-slim` -If you don't want the extra dependencies, install `typer-slim` instead. +If you don't want the extra standard optional dependencies, install `typer-slim` instead. When you install with: @@ -369,15 +366,15 @@ When you install with: pip install typer ``` -...it's the equivalent of: +...it includes the same code and dependencies as: ```bash pip install "typer-slim[standard]" ``` -The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. +The `standard` extra dependencies are `rich` and `shellingham`. -**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. +**Note**: The `typer` command is only included in the `typer` package. ## License diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index 6fb8075c87..6cec65fe23 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -68,12 +68,12 @@ The first step is to install **Typer**: ```console $ pip install typer ---> 100% -Successfully installed typer click shellingham rich typer-cli +Successfully installed typer click shellingham rich ```
-By default, `typer` comes with `rich`, `shellingham`, and `typer-cli`. +By default, `typer` comes with `rich` and `shellingham`. !!! note If you are an advanced user and want to opt out of these default extra dependencies, you can instead install `typer-slim`. @@ -82,7 +82,7 @@ By default, `typer` comes with `rich`, `shellingham`, and `typer-cli`. pip install typer ``` - ...is the equivalent of: + ...includes the same optional dependencies as: ```bash pip install "typer-slim[standard]" diff --git a/pdm_build.py b/pdm_build.py new file mode 100644 index 0000000000..4629801f0e --- /dev/null +++ b/pdm_build.py @@ -0,0 +1,55 @@ +import os +from typing import Any, Dict, List + +from pdm.backend.hooks import Context + +TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "typer") + + +def pdm_build_initialize(context: Context): + metadata = context.config.metadata + # Get main version + version = metadata["version"] + # Get package names to keep in sync with the same main version + sync_dependencies: List[str] = context.config.data["tool"]["tiangolo"][ + "_internal-slim-build" + ]["sync-dependencies"] + # Get custom config for the current package, from the env var + config: Dict[str, Any] = context.config.data["tool"]["tiangolo"][ + "_internal-slim-build" + ]["packages"][TIANGOLO_BUILD_PACKAGE] + project_config: Dict[str, Any] = config["project"] + # Get main optional dependencies, extras + optional_dependencies: Dict[str, List[str]] = metadata.get( + "optional-dependencies", {} + ) + # Get custom optional dependencies name to always include in this (non-slim) package + include_optional_dependencies: List[str] = config.get( + "include-optional-dependencies", [] + ) + # Override main [project] configs with custom configs for this package + for key, value in project_config.items(): + metadata[key] = value + # Get custom build config for the current package + build_config: Dict[str, Any] = ( + config.get("tool", {}).get("pdm", {}).get("build", {}) + ) + # Override PDM build config with custom build config for this package + for key, value in build_config.items(): + context.config.build_config[key] = value + # Get main dependencies + dependencies: List[str] = metadata.get("dependencies", []) + # Add optional dependencies to the default dependencies for this (non-slim) package + for include_optional in include_optional_dependencies: + optional_dependencies_group = optional_dependencies.get(include_optional, []) + dependencies.extend(optional_dependencies_group) + # Sync versions in dependencies + new_dependencies = [] + for dep in dependencies: + if dep in sync_dependencies: + new_dep = f"{dep}=={version}" + new_dependencies.append(new_dep) + else: + new_dependencies.append(dep) + if new_dependencies != dependencies: + metadata["dependencies"] = new_dependencies diff --git a/pyproject.toml b/pyproject.toml index f5abe95d3c..b648d38ad4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,15 +3,12 @@ requires = ["pdm-backend"] build-backend = "pdm.backend" [project] -# pip install typer-slim: is only the Typer library, without extras -# pip install typer: is typer-slim[standard], with extras and typer-cli -name = "typer-slim" +name = "typer" dynamic = ["version"] description = "Typer, build great CLIs. Easy to code. Based on Python type hints." authors = [ {name = "Sebastián Ramírez", email = "tiangolo@gmail.com"}, ] -readme = "README.md" requires-python = ">=3.7" classifiers = [ "Intended Audience :: Information Technology", @@ -38,16 +35,12 @@ dependencies = [ "click >= 8.0.0", "typing-extensions >= 3.7.4.3", ] - +readme = "README.md" [project.urls] Documentation = "https://typer.tiangolo.com/" homepage = "https://github.com/tiangolo/typer" [project.optional-dependencies] -all = [ - "shellingham >=1.3.0", - "rich >=10.11.0", -] standard = [ "shellingham >=1.3.0", "rich >=10.11.0", @@ -65,6 +58,50 @@ source-includes = [ "scripts/", ] +[tool.tiangolo._internal-slim-build] +sync-dependencies = [ + "typer-slim[standard]", + "typer-cli", + "typer" +] + +[tool.tiangolo._internal-slim-build.packages.typer-slim.project] +name = "typer-slim" + +[tool.tiangolo._internal-slim-build.packages.typer] +include-optional-dependencies = ["standard"] + +[tool.tiangolo._internal-slim-build.packages.typer.project] +optional-dependencies = {} + +[tool.tiangolo._internal-slim-build.packages.typer.project.scripts] +typer = "typer.cli:main" + +[tool.tiangolo._internal-slim-build.packages.typer-cli.project] +name = "typer-cli" +readme = "typer-cli/README.md" +dependencies = [ + "typer", +] +optional-dependencies = {} + +[tool.tiangolo._internal-slim-build.packages.typer-cli.tool.pdm.build] +# excludes needs to explicitly exclude the top level python packages, +# otherwise PDM includes them by default +# A "*" glob pattern can't be used here because in PDM internals, the patterns are put +# in a set (unordered, order varies) and each excluded file is assigned one of the +# glob patterns that matches, as the set is unordered, the matched pattern could be "*" +# independent of the order here. And then the internal code would give it a lower score +# than the one for a default included file. +# By not using "*" and explicitly excluding the top level packages, they get a higher +# score than the default inclusion +excludes = ["typer", "tests", "pdm_build.py"] +# source-includes needs to explicitly define some value because PDM will check the +# truthy value of the list, and if empty, will include some defaults, including "tests", +# an empty string doesn't match anything, but makes the list truthy, so that PDM +# doesn't override it during the build. +source-includes = [""] + [tool.isort] profile = "black" known_third_party = ["typer", "click"] diff --git a/typer_cli_package/README.md b/typer-cli/README.md similarity index 82% rename from typer_cli_package/README.md rename to typer-cli/README.md index dba1a0dcf7..0ebe65102c 100644 --- a/typer_cli_package/README.md +++ b/typer-cli/README.md @@ -30,9 +30,13 @@ Typer is a library for building Date: Fri, 5 Apr 2024 00:29:53 +0000 Subject: [PATCH 35/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 733c50c3e7..655a8855a9 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,10 @@ * ✨ Add support for `typer ./someprogram.py utils docs --title`. PR [#782](https://github.com/tiangolo/typer/pull/782) by [@tiangolo](https://github.com/tiangolo). +### Fixes + +* 🐛 Fix broken installation when upgrading from `typer <0.12.0` to `typer >=0.12.0`, make `typer` independent of `typer-slim`, include `typer` command in `typer` package. PR [#791](https://github.com/tiangolo/typer/pull/791) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 👷 Add cron to run test once a week on monday. PR [#783](https://github.com/tiangolo/typer/pull/783) by [@estebanx64](https://github.com/estebanx64). From 3d1c32bf93214b0ac9c6b8d04a3daae2bbf2f74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 4 Apr 2024 19:39:28 -0500 Subject: [PATCH 36/37] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release-notes.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 655a8855a9..76a0432ffc 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,15 @@ ## Latest Changes +## 0.12.1 + +Now you don't need to install `typer[all]`. When you install `typer` it comes with the default optional dependencies and the `typer` command. + +If you don't want the extra optional dependencies (`rich` and `shellingham`), you can install `typer-slim` instead. + +You can also install `typer-slim[standard]`, which includes the default optional dependencies, but not the `typer` command. + +Now the package `typer-cli` doesn't add anything on top of what `typer` has, it only depends on `typer`, and is there only for backwards compatibility, so that projects that depend on `typer-cli` can get the latest features of the `typer` command while they upgrade their dependencies to require `typer` directly. + ### Features * ✨ Add support for `typer ./someprogram.py utils docs --title`. PR [#782](https://github.com/tiangolo/typer/pull/782) by [@tiangolo](https://github.com/tiangolo). @@ -8,12 +18,26 @@ * 🐛 Fix broken installation when upgrading from `typer <0.12.0` to `typer >=0.12.0`, make `typer` independent of `typer-slim`, include `typer` command in `typer` package. PR [#791](https://github.com/tiangolo/typer/pull/791) by [@tiangolo](https://github.com/tiangolo). +This fixes a problem that would break the `typer` installation directory when upgrading from `typer <0.12.0` to `typer >=0.12.0`, see issue [#790](https://github.com/tiangolo/typer/issues/790). + +By installing the latest version (`0.12.1`) it fixes it, for any previous version, even if the installation directory was already broken by the previous upgrade. + ### Internal * 👷 Add cron to run test once a week on monday. PR [#783](https://github.com/tiangolo/typer/pull/783) by [@estebanx64](https://github.com/estebanx64). ## 0.12.0 +In version `0.12.0`, the `typer` package depends on `typer-slim[standard]` which includes the default dependencies (instead of `typer[all]`) and `typer-cli` (that provides the `typer` command). + +If you don't want the extra optional dependencies (`rich` and `shellingham`), you can install `typer-slim` instead. + +You can also install `typer-slim[standard]`, which includes the default optional dependencies, but not the `typer` command. + +In version `0.12.0` the `typer-cli` package only provides the `typer` command, but the code is still in the main code, so even without installing `typer-cli`, it can be called with `python -m typer`. + +This approach of having `typer` depend on `typer-slim[standard]` instead of including the whole code and dependencies itself caused an issue when upgrading from `typer <0.12.0` to `typer >=0.12.0`, see issue [#790](https://github.com/tiangolo/typer/issues/790). This is fixed in version `0.12.1`. + ### Features * ✨ Add `typer-slim` package without extras, make `typer` include `typer-slim[default]` and integrate Typer CLI (`typer` command) into Typer. PR [#780](https://github.com/tiangolo/typer/pull/780) by [@tiangolo](https://github.com/tiangolo). From f94b484450393f6a5cd064000ccc5b05e3bab10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 4 Apr 2024 19:40:04 -0500 Subject: [PATCH 37/37] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typer/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typer/__init__.py b/typer/__init__.py index 53a450970e..54d9c02214 100644 --- a/typer/__init__.py +++ b/typer/__init__.py @@ -1,6 +1,6 @@ """Typer, build great CLIs. Easy to code. Based on Python type hints.""" -__version__ = "0.12.1.dev2" +__version__ = "0.12.1" from shutil import get_terminal_size as get_terminal_size