From 0e028ce7eedf2390708eec09ebb1f760e2a23941 Mon Sep 17 00:00:00 2001 From: Steve Holden Date: Wed, 25 Jun 2025 04:57:47 +0100 Subject: [PATCH 1/2] Fix problem that validates empty inputs when empty_valid = false. The new test at tests/input/test_input_validation.py::test_valid_empty failed until the sequence of operations in the Input.validate function was refactored. Existing test continue to pass. --- src/textual/widgets/_input.py | 21 +++++++++++---------- tests/input/test_input_validation.py | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index 326e535958..6a2f04ab3e 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -149,7 +149,7 @@ class Input(ScrollView): | ctrl+k | Delete everything to the right of the cursor. | | ctrl+x | Cut selected text. | | ctrl+c | Copy selected text. | - | ctrl+v | Paste text from the clipboard. | + | ctrl+v | Paste text from the clipboard. | """ COMPONENT_CLASSES: ClassVar[set[str]] = { @@ -187,9 +187,9 @@ class Input(ScrollView): } &:focus { - border: tall $border; + border: tall $border; background-tint: $foreground 5%; - + } &>.input--cursor { background: $input-cursor-background; @@ -207,12 +207,12 @@ class Input(ScrollView): } &.-invalid:focus { border: tall $error; - } + } &:ansi { background: ansi_default; color: ansi_default; - &>.input--cursor { + &>.input--cursor { text-style: reverse; } &>.input--placeholder, &>.input--suggestion { @@ -224,8 +224,8 @@ class Input(ScrollView): } &.-invalid:focus { border: tall ansi_red; - } - + } + } } @@ -571,13 +571,14 @@ def set_classes() -> None: self.set_class(not valid, "-invalid") self.set_class(valid, "-valid") - # If no validators are supplied, and therefore no validation occurs, we return None. - if not self.validators: + # Empty inputs are always OK if valid_empty is set. + if self.valid_empty and not value: self._valid = True set_classes() return None - if self.valid_empty and not value: + # If no validators are supplied, and therefore no validation occurs, we return None. + if not self.validators: self._valid = True set_classes() return None diff --git a/tests/input/test_input_validation.py b/tests/input/test_input_validation.py index 3ea17191b5..001c1d9b69 100644 --- a/tests/input/test_input_validation.py +++ b/tests/input/test_input_validation.py @@ -214,6 +214,7 @@ async def test_valid_empty(): input = app.query_one(Input) await pilot.press("1", "backspace") + assert input.value == '' assert not input.has_class("-valid") assert input.has_class("-invalid") From 694b03e12f5706154e669235bbe703740da0bc63 Mon Sep 17 00:00:00 2001 From: Steve Holden Date: Wed, 25 Jun 2025 05:08:24 +0100 Subject: [PATCH 2/2] Add explanatory comment. --- tests/input/test_input_validation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/input/test_input_validation.py b/tests/input/test_input_validation.py index 001c1d9b69..927523739d 100644 --- a/tests/input/test_input_validation.py +++ b/tests/input/test_input_validation.py @@ -211,15 +211,15 @@ async def test_none_validate_on_means_all_validations_happen(): async def test_valid_empty(): app = InputApp(None) async with app.run_test() as pilot: - input = app.query_one(Input) + input = app.query_one(Input) # valid_empty=False await pilot.press("1", "backspace") - assert input.value == '' + assert input.value == '' # Empty value: invalid assert not input.has_class("-valid") assert input.has_class("-invalid") input.valid_empty = True - assert input.has_class("-valid") + assert input.has_class("-valid") # Empty value: now acceptble assert not input.has_class("-invalid")