diff --git a/click_repl/_completer.py b/click_repl/_completer.py index 2c592d6..67b8bda 100644 --- a/click_repl/_completer.py +++ b/click_repl/_completer.py @@ -274,7 +274,10 @@ def get_completions(self, document, complete_event=None): if self.parsed_args != args: self.parsed_args = args - self.parsed_ctx = _resolve_context(args, self.ctx) + try: + self.parsed_ctx = _resolve_context(args, self.ctx) + except Exception: + return [] # autocompletion for nonexistent cmd can throw here self.ctx_command = self.parsed_ctx.command if getattr(self.ctx_command, "hidden", False): diff --git a/tests/test_completion/test_common_tests/test_cmd_completion.py b/tests/test_completion/test_common_tests/test_cmd_completion.py new file mode 100644 index 0000000..6238668 --- /dev/null +++ b/tests/test_completion/test_common_tests/test_cmd_completion.py @@ -0,0 +1,35 @@ +import click +from unittest import TestCase +from prompt_toolkit.document import Document +from click_repl import ClickCompleter + + +@click.group() +def cli(): + pass + + +@cli.group() +def cmd(): + pass + + +@cmd.command() +def subcmd(): + pass + + +class Test_Command_Autocompletion(TestCase): + def setUp(self): + self.c = ClickCompleter(cli, click.Context(cli)) + + def test_valid_subcmd(self): + res = list(self.c.get_completions(Document("cmd s"))) + self.assertListEqual([i.text for i in res], ["subcmd"]) + + def test_not_valid_subcmd(self): + try: + res = list(self.c.get_completions(Document("not cmd"))) + except Exception as e: + self.fail(f"Autocompletion raised exception: {e}") + self.assertListEqual(res, [])