Skip to content

Commit

Permalink
Make Choice.shortcut_key property with setter
Browse files Browse the repository at this point in the history
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa. Add tests for fix.

Fixes #340

Signed-off-by: Ross Williams <[email protected]>
  • Loading branch information
overhacked committed Jul 9, 2024
1 parent cf10f3e commit c333dec
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 13 deletions.
38 changes: 25 additions & 13 deletions questionary/prompts/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Expand All @@ -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

Expand All @@ -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.
Expand Down Expand Up @@ -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 "-) "
Expand Down
25 changes: 25 additions & 0 deletions tests/prompts/test_select.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from copy import copy

import pytest

from questionary import Choice
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit c333dec

Please sign in to comment.