Textualize/textual

[Bug] Describe failures for Integer validator

Closed this issue · 2 comments

I encountered a small issue using input validators.
I have an Input widget with an Integer validator set. The error occurs when i try to get the ValidationResult.failure_descriptions property when the input is empty.

Since the Integer validator inherits from the Number validator, failures of type Number.NotANumber and Number.NotInRange may occur. The failures are found when the input is empty but when I try to get access to the failure descriptions, it is empty because of the following code :

class Integer(Number):
    """Validator which ensures the value is an integer which falls within a range."""

    class NotAnInteger(Failure):
        """Indicates a failure due to the value not being a valid integer."""

    def validate(self, value: str) -> ValidationResult:
        """Ensure that `value` is an integer, optionally within a range.

        Args:
            value: The value to validate.

        Returns:
            The result of the validation.
        """
        # First, check that we're dealing with a number in the range.
        number_validation_result = super().validate(value)
        if not number_validation_result.is_valid:
            return number_validation_result

        # We know it's a number, but is that number an integer?
        is_integer = float(value).is_integer()
        if not is_integer:
            return ValidationResult.failure([Integer.NotAnInteger(self, value)])

        return self.success()

    def describe_failure(self, failure: Failure) -> str | None:
        """Describes why the validator failed.

        Args:
            failure: Information about why the validation failed.

        Returns:
            A string description of the failure.
        """
        if isinstance(failure, Integer.NotAnInteger):
            return f"Must be a valid integer."
        elif isinstance(failure, Integer.NotInRange):
            if self.minimum is None and self.maximum is not None:
                return f"Must be less than or equal to {self.maximum}."
            elif self.minimum is not None and self.maximum is None:
                return f"Must be greater than or equal to {self.minimum}."
            else:
                return f"Must be between {self.minimum} and {self.maximum}."
        else:
            return None

In the method describe_failure, only Integer.NotAnInteger and Integer.NotInRange failures are tested, but not the ones from Number...
Otherwise, the Integer.NotInRange does not seem to be raised in the Integer.validate() method.
Feel free to ask more information if I'm not clear enough. :)

Textual Diagnostics

Versions

Name Value
Textual 0.55.0
Rich 13.7.1

Python

Name Value
Version 3.11.8
Implementation CPython
Compiler GCC 11.2.0
Executable /home/alexandre/miniconda3/envs/analytics/bin/python

Operating System

Name Value
System Linux
Release 5.15.0-60-generic
Version #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023

Terminal

Name Value
Terminal Application GNOME Terminal
TERM xterm-256color
COLORTERM truecolor
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=204, height=53
legacy_windows False
min_width 1
max_width 204
is_terminal True
encoding utf-8
max_height 53
justify None
overflow None
no_wrap False
highlight None
markup None
height None

We found the following entries in the FAQ which you may find helpful:

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by FAQtory

Don't forget to star the repository!

Follow @textualizeio for Textual updates.