diff --git a/tests/test_completion/path_example.py b/tests/test_completion/path_example.py new file mode 100644 index 0000000000..887ebfef24 --- /dev/null +++ b/tests/test_completion/path_example.py @@ -0,0 +1,14 @@ +from pathlib import Path + +import typer + +app = typer.Typer() + + +@app.command() +def f(p: Path): + print(p) + + +if __name__ == "__main__": + app() diff --git a/tests/test_completion/test_completion_path.py b/tests/test_completion/test_completion_path.py new file mode 100644 index 0000000000..f7bae79615 --- /dev/null +++ b/tests/test_completion/test_completion_path.py @@ -0,0 +1,30 @@ +import os +import subprocess +import sys + +from . import path_example as mod + + +def test_script(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", mod.__file__, "path/to/deadpool"], + capture_output=True, + encoding="utf-8", + ) + assert result.returncode == 0 + assert "deadpool" in result.stdout + + +def test_completion_path_bash(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", mod.__file__, " "], + capture_output=True, + encoding="utf-8", + env={ + **os.environ, + "_PATH_EXAMPLE.PY_COMPLETE": "complete_bash", + "COMP_WORDS": "path_example.py ", + "COMP_CWORD": "2", + }, + ) + assert result.returncode == 0 diff --git a/typer/main.py b/typer/main.py index e552f6335f..508d96617e 100644 --- a/typer/main.py +++ b/typer/main.py @@ -44,6 +44,7 @@ ParamMeta, Required, TyperInfo, + TyperPath, ) from .utils import get_params_from_function @@ -743,7 +744,7 @@ def get_click_type( or parameter_info.path_type or parameter_info.resolve_path ): - return click.Path( + return TyperPath( exists=parameter_info.exists, file_okay=parameter_info.file_okay, dir_okay=parameter_info.dir_okay, diff --git a/typer/models.py b/typer/models.py index 544e504761..e0bddb965b 100644 --- a/typer/models.py +++ b/typer/models.py @@ -531,3 +531,14 @@ def __init__( self.pretty_exceptions_enable = pretty_exceptions_enable self.pretty_exceptions_show_locals = pretty_exceptions_show_locals self.pretty_exceptions_short = pretty_exceptions_short + + +class TyperPath(click.Path): + # Overwrite Click's behaviour to be compatible with Typer's autocompletion system + def shell_complete( + self, ctx: click.Context, param: click.Parameter, incomplete: str + ) -> List[click.shell_completion.CompletionItem]: + """Return an empty list so that the autocompletion functionality + will work properly from the commandline. + """ + return []