diff --git a/tests/test_ambiguous_params.py b/tests/test_ambiguous_params.py index 0693c8e9aa..e15bab1071 100644 --- a/tests/test_ambiguous_params.py +++ b/tests/test_ambiguous_params.py @@ -229,3 +229,21 @@ def cmd( ) def test_error_rendering(error, message): assert str(error) == message + + +def test_keyword_only_without_default_becomes_option(): + app = typer.Typer() + + @app.command() + def cmd(*, my_param): + print(my_param) + + # Check that it works with the keyword + result = runner.invoke(app, ["--my-param", "hello"]) + assert result.exit_code == 0, result.output + assert "hello" in result.output + + # Check that it fails without the keyword + result = runner.invoke(app, ["hello"]) + assert result.exit_code != 0, result.output + assert "Missing option" in result.output, result.output diff --git a/typer/main.py b/typer/main.py index 2fdc09e1ac..09d7944a71 100644 --- a/typer/main.py +++ b/typer/main.py @@ -814,7 +814,10 @@ def get_click_param( default_value = parameter_info.default elif param.default == Required or param.default is param.empty: required = True - parameter_info = ArgumentInfo() + if param.kind == inspect.Parameter.KEYWORD_ONLY: + parameter_info = OptionInfo() + else: + parameter_info = ArgumentInfo() else: default_value = param.default parameter_info = OptionInfo() diff --git a/typer/models.py b/typer/models.py index e0bddb965b..ee1ffa2d4c 100644 --- a/typer/models.py +++ b/typer/models.py @@ -514,10 +514,12 @@ def __init__( name: str, default: Any = inspect.Parameter.empty, annotation: Any = inspect.Parameter.empty, + kind: inspect._ParameterKind = inspect.Parameter.POSITIONAL_OR_KEYWORD, ) -> None: self.name = name self.default = default self.annotation = annotation + self.kind = kind class DeveloperExceptionConfig: diff --git a/typer/utils.py b/typer/utils.py index 81dc4dd61d..091bd8cf7c 100644 --- a/typer/utils.py +++ b/typer/utils.py @@ -185,6 +185,6 @@ def get_params_from_function(func: Callable[..., Any]) -> Dict[str, ParamMeta]: default = parameter_info params[param.name] = ParamMeta( - name=param.name, default=default, annotation=annotation + name=param.name, default=default, annotation=annotation, kind=param.kind ) return params