diff --git a/src/textual/widgets/_selection_list.py b/src/textual/widgets/_selection_list.py index c5f1a22d9..ca8fd0cac 100644 --- a/src/textual/widgets/_selection_list.py +++ b/src/textual/widgets/_selection_list.py @@ -199,7 +199,8 @@ class SelectionList(Generic[SelectionType], OptionList): def __init__( self, - *selections: tuple[TextType, SelectionType] + *selections: Selection + | tuple[TextType, SelectionType] | tuple[TextType, SelectionType, bool], name: str | None = None, id: str | None = None, @@ -397,7 +398,8 @@ class SelectionList(Generic[SelectionType], OptionList): def _make_selection( self, - selection: tuple[TextType, SelectionType] + selection: Selection + | tuple[TextType, SelectionType] | tuple[TextType, SelectionType, bool], ) -> Selection[SelectionType]: """Turn incoming selection data into a `Selection` instance. @@ -411,19 +413,31 @@ class SelectionList(Generic[SelectionType], OptionList): Raises: SelectionError: If the selection was badly-formed. """ - if len(selection) == 3: - label, value, selected = cast( - "tuple[TextType, SelectionType, bool]", selection - ) - elif len(selection) == 2: - label, value, selected = cast( - "tuple[TextType, SelectionType, bool]", (*selection, False) - ) - else: - raise SelectionError(f"Expected 2 or 3 values, got {len(selection)}") - if selected: - self._select(value) - return Selection(label, value) + + # If we've been given a tuple of some sort, turn that into a proper + # Selection. + if isinstance(selection, tuple): + if len(selection) == 3: + label, value, selected = cast( + "tuple[TextType, SelectionType, bool]", selection + ) + elif len(selection) == 2: + label, value, selected = cast( + "tuple[TextType, SelectionType, bool]", (*selection, False) + ) + else: + raise SelectionError(f"Expected 2 or 3 values, got {len(selection)}") + selection = Selection(label, value, selected) + + # 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: """Toggle the state of the highlighted selection. diff --git a/tests/selection_list/test_selection_list_create.py b/tests/selection_list/test_selection_list_create.py index 1a4982c29..f756ff068 100644 --- a/tests/selection_list/test_selection_list_create.py +++ b/tests/selection_list/test_selection_list_create.py @@ -25,6 +25,8 @@ class SelectionListApp(App[None]): ("0", 0), ("1", 1, False), ("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.""" async with SelectionListApp().run_test() as pilot: selections = pilot.app.query_one(SelectionList) - assert selections.option_count == 3 - for n in range(3): + assert selections.option_count == 5 + for n in range(5): 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.""" async with SelectionListApp().run_test() as pilot: 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(-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: """It should be possible to add more items to a selection list.""" async with SelectionListApp().run_test() as pilot: 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 - selections.add_options([Selection("5", 5), ("6", 6), ("7", 7, True)]) - assert selections.option_count == 8 + selections.add_option(("5", 5)) + 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([]) - assert selections.option_count == 8 + assert selections.option_count == 11 async def test_add_non_selections() -> None: