diff --git a/questionary/prompts/common.py b/questionary/prompts/common.py index 827629db..4c33b834 100644 --- a/questionary/prompts/common.py +++ b/questionary/prompts/common.py @@ -69,8 +69,7 @@ class Choice: checked: Optional[bool] """Whether the choice is initially selected""" - shortcut_key: Optional[str] - """A shortcut key for the choice""" + __shortcut_key: Optional[Union[str, bool]] description: Optional[str] """Choice description""" @@ -86,6 +85,7 @@ def __init__( ) -> None: self.disabled = disabled self.title = title + self.shortcut_key = shortcut_key self.checked = checked if checked is not None else False self.description = description @@ -96,17 +96,6 @@ def __init__( else: self.value = title - if shortcut_key is not None: - if isinstance(shortcut_key, bool): - self.auto_shortcut = shortcut_key - self.shortcut_key = None - else: - self.shortcut_key = str(shortcut_key) - self.auto_shortcut = False - else: - self.shortcut_key = None - self.auto_shortcut = True - @staticmethod def build(c: Union[str, "Choice", Dict[str, Any]]) -> "Choice": """Create a choice object from different representations. @@ -134,6 +123,29 @@ def build(c: Union[str, "Choice", Dict[str, Any]]) -> "Choice": c.get("description", None), ) + @property + def shortcut_key(self) -> Optional[Union[str, bool]]: + """A shortcut key for the choice""" + return self.__shortcut_key + + @shortcut_key.setter + def shortcut_key(self, key: Optional[Union[str, bool]]): + if key is not None: + if isinstance(key, bool): + self.auto_shortcut = key + self.__shortcut_key = None + else: + self.__shortcut_key = str(key) + self.auto_shortcut = False + else: + self.__shortcut_key = None + self.auto_shortcut = True + + @shortcut_key.deleter + def shortcut_key(self): + self.__shortcut_key = None + self.auto_shortcut = True + def get_shortcut_title(self): if self.shortcut_key is None: return "-) " diff --git a/tests/prompts/test_select.py b/tests/prompts/test_select.py index 1d3eaa57..c4b9221d 100644 --- a/tests/prompts/test_select.py +++ b/tests/prompts/test_select.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from copy import copy + import pytest from questionary import Choice @@ -199,6 +201,29 @@ def test_allow_shortcut_key_with_True(): assert result == "bazz" +def test_auto_shortcut_key_stable_in_loop(): + message = "Foo message" + choices = [ + Choice("foo"), + Choice("bar"), + ] + kwargs = { + "choices": choices, + "use_shortcuts": True, + } + text = "\r" + + result, cli = feed_cli_with_input("select", message, text, **kwargs) + assert result == "foo" + result_shortcut_keys = [copy(c.shortcut_key) for c in choices] + result2, cli = feed_cli_with_input("select", message, text, **kwargs) + assert result2 == "foo" + result2_shortcut_keys = [copy(c.shortcut_key) for c in choices] + assert ( + result_shortcut_keys == result2_shortcut_keys + ), "Shortcut keys changed across two runs of 'select'" + + def test_select_initial_choice_with_value(): message = "Foo message" choice = Choice(title="bazz", value="bar")