Allow passing a Selection into a SelctionList

Up until now I've only been allowing tuples; mostly a hangover from the
initial take on this. Things have drifted a bit now and I feel it makes
sense to allow Selection instances in too.
This commit is contained in:
Dave Pearson
2023-05-24 10:09:53 +01:00
parent da1faf8fb9
commit d3fe23f0bc
2 changed files with 52 additions and 26 deletions

View File

@@ -199,7 +199,8 @@ class SelectionList(Generic[SelectionType], OptionList):
def __init__( def __init__(
self, self,
*selections: tuple[TextType, SelectionType] *selections: Selection
| tuple[TextType, SelectionType]
| tuple[TextType, SelectionType, bool], | tuple[TextType, SelectionType, bool],
name: str | None = None, name: str | None = None,
id: str | None = None, id: str | None = None,
@@ -397,7 +398,8 @@ class SelectionList(Generic[SelectionType], OptionList):
def _make_selection( def _make_selection(
self, self,
selection: tuple[TextType, SelectionType] selection: Selection
| tuple[TextType, SelectionType]
| tuple[TextType, SelectionType, bool], | tuple[TextType, SelectionType, bool],
) -> Selection[SelectionType]: ) -> Selection[SelectionType]:
"""Turn incoming selection data into a `Selection` instance. """Turn incoming selection data into a `Selection` instance.
@@ -411,6 +413,10 @@ class SelectionList(Generic[SelectionType], OptionList):
Raises: Raises:
SelectionError: If the selection was badly-formed. SelectionError: If the selection was badly-formed.
""" """
# If we've been given a tuple of some sort, turn that into a proper
# Selection.
if isinstance(selection, tuple):
if len(selection) == 3: if len(selection) == 3:
label, value, selected = cast( label, value, selected = cast(
"tuple[TextType, SelectionType, bool]", selection "tuple[TextType, SelectionType, bool]", selection
@@ -421,9 +427,17 @@ class SelectionList(Generic[SelectionType], OptionList):
) )
else: else:
raise SelectionError(f"Expected 2 or 3 values, got {len(selection)}") raise SelectionError(f"Expected 2 or 3 values, got {len(selection)}")
if selected: selection = Selection(label, value, selected)
self._select(value)
return Selection(label, value) # At this point we should have a proper selection.
assert isinstance(selection, Selection)
# If the initial state for this is that it's selected, add it to the
# selected collection.
if selection.initial_state:
self._select(selection.value)
return selection
def _toggle_highlighted_selection(self) -> None: def _toggle_highlighted_selection(self) -> None:
"""Toggle the state of the highlighted selection. """Toggle the state of the highlighted selection.

View File

@@ -25,6 +25,8 @@ class SelectionListApp(App[None]):
("0", 0), ("0", 0),
("1", 1, False), ("1", 1, False),
("2", 2, True), ("2", 2, True),
Selection("3", 3, id="3"),
Selection("4", 4, True, id="4"),
) )
@@ -32,8 +34,8 @@ async def test_all_parameters_become_selctions() -> None:
"""All input parameters to a list should become selections.""" """All input parameters to a list should become selections."""
async with SelectionListApp().run_test() as pilot: async with SelectionListApp().run_test() as pilot:
selections = pilot.app.query_one(SelectionList) selections = pilot.app.query_one(SelectionList)
assert selections.option_count == 3 assert selections.option_count == 5
for n in range(3): for n in range(5):
assert isinstance(selections.get_option_at_index(n), Selection) assert isinstance(selections.get_option_at_index(n), Selection)
@@ -41,24 +43,34 @@ async def test_get_selection_by_index() -> None:
"""It should be possible to get a selection by index.""" """It should be possible to get a selection by index."""
async with SelectionListApp().run_test() as pilot: async with SelectionListApp().run_test() as pilot:
option_list = pilot.app.query_one(SelectionList) option_list = pilot.app.query_one(SelectionList)
for n in range(3): for n in range(5):
assert option_list.get_option_at_index(n).prompt == Text(str(n)) assert option_list.get_option_at_index(n).prompt == Text(str(n))
assert option_list.get_option_at_index(-1).prompt == Text("2") assert option_list.get_option_at_index(-1).prompt == Text("4")
async def test_get_selection_by_id() -> None:
"""It should be possible to get a selection by ID."""
async with SelectionListApp().run_test() as pilot:
option_list = pilot.app.query_one(SelectionList)
assert option_list.get_option("3").prompt == Text("3")
assert option_list.get_option("4").prompt == Text("4")
async def test_add_later() -> None: async def test_add_later() -> None:
"""It should be possible to add more items to a selection list.""" """It should be possible to add more items to a selection list."""
async with SelectionListApp().run_test() as pilot: async with SelectionListApp().run_test() as pilot:
selections = pilot.app.query_one(SelectionList) selections = pilot.app.query_one(SelectionList)
assert selections.option_count == 3
selections.add_option(("3", 3))
assert selections.option_count == 4
selections.add_option(Selection("4", 4))
assert selections.option_count == 5 assert selections.option_count == 5
selections.add_options([Selection("5", 5), ("6", 6), ("7", 7, True)]) selections.add_option(("5", 5))
assert selections.option_count == 8 assert selections.option_count == 6
selections.add_option(Selection("6", 6))
assert selections.option_count == 7
selections.add_options(
[Selection("7", 7), Selection("8", 8, True), ("9", 9), ("10", 10, True)]
)
assert selections.option_count == 11
selections.add_options([]) selections.add_options([])
assert selections.option_count == 8 assert selections.option_count == 11
async def test_add_non_selections() -> None: async def test_add_non_selections() -> None: