Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

### Fixed

- Fix crash when using Input in a DEFAULT_MODE screen https://github.com/Textualize/textual/pull/6492

### Added

- Added `DOM.update_classes` https://github.com/Textualize/textual/pull/6478
Expand Down
5 changes: 4 additions & 1 deletion src/textual/widgets/_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def cursor_position(self, position: int) -> None:
"""Set the current position of the cursor."""
self.selection = Selection.cursor(position)

selection: Reactive[Selection] = reactive(Selection.cursor(0))
selection: Reactive[Selection] = reactive(Selection.cursor(0), init=False)
"""The currently selected range of text."""

placeholder = reactive("")
Expand Down Expand Up @@ -505,6 +505,9 @@ def validate_selection(self, selection: Selection) -> Selection:
return Selection(clamp(start, 0, value_length), clamp(end, 0, value_length))

def _watch_selection(self, selection: Selection) -> None:
if not self.is_mounted:
return

self.app.clear_selection()
self.app.cursor_position = self.cursor_screen_offset
if not self._initial_value:
Expand Down
34 changes: 34 additions & 0 deletions tests/input/test_input_default_mode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import asyncio

import pytest

from textual.app import App, ComposeResult
from textual.screen import Screen
from textual.widgets import Input


class DefaultScreen(Screen):
def compose(self) -> ComposeResult:
yield Input()
yield Input("Hello, world!")


class InputApp(App):
DEFAULT_MODE = "default"
MODES = {"default": DefaultScreen}


@pytest.mark.skipif(
not hasattr(asyncio, "eager_task_factory"), reason="only occurs with eager tasks"
)
async def test_input_default_mode():
"""Test that Input in a DEFAULT_MODE Screen doesn't crash.

Regression test for https://github.com/textualize/textual/issues/6444.

"""
# changing this will not affect other tests since pytest-asyncio runs every function
# in a new event loop by default
asyncio.get_running_loop().set_task_factory(asyncio.eager_task_factory)
async with InputApp().run_test():
pass