Skip to content

Validators

Context

BasicQuestion allows the user to provide arbitrary text as the answer to the question. However, there are frequently constraints on what is considered a valid answer. Providing a Validator for the question allows columbo to verify that the text provided by the user satisfies those constraints. If the answer is not valid, columbo will tell the user that the answer is not valid and ask them to try again.

The default value for the BasicQuestion must satisfy the Validator. An exception will be raised if that is not the case. This is because it could lead to: * An infinite loop when prompting a user * Command line parsing always failing if a value is not given

Note

While Choice and Confirm do not expose a validator argument they still ensure that the answer is valid. A Confirm question will only continue when Y, N, or Enter are pressed. Any other keys will be ignored. A Choice question will only continue when Enter is pressed if the input matches the number columbo assigned to one of the choices.

Validator Structure

A Validator must be a function which has the following type signature: Callable[[str, Answers], ValidationResponse]1. We'll walk through this signature explaining each part.

A Validator takes two arguments: a string (which is the response provided by the user to a question) and an Answers dictionary containing the answer for each previous question.

The Validator must return a ValidationResponse which is a type alias for: Union[ValidationFailure, ValidationSuccess]1. Thus, a Validator must return either a ValidationFailure or a ValidationSuccess object. You should use a ValidationSuccess when the user's response is valid and ValidationFailure when the user's response is invalid. Both ValidationFailure and ValidationSuccess have a valid attribute that is False and True, respectively. A ValidationFailure requires that you provide an error which describes why the given value was invalid (columbo will display this message before asking users to answer the question again so users get some feedback about what they are doing wrong).

Upgrading Validator Structure

Validators could return Optional[str] before <0.10.0, this was removed in 1.0.0.

The docs in this section detail how to upgrade a Validator from a columbo version < 0.10.0 to the newer Validator structure. Feel free to skip this section if it's not pertinent to you.

Previously, a Validator would return either an error message (as a string) if validation failed or None if the validation succeeded. To update a Validator, you should update the validator function to return ValidationFailure if validation fails and ValidationSuccess if the validation succeeds. The table below describes the old and new return values for different validation statuses.

Validation Status Old Return Value (before 0.10.0) New Return Value (since 0.10.0)
Failed "Some error message" ValidationFailure(error="Some error message")
Succeeded None ValidationSuccess()

Example Validator

Let's say we were asking for a user's email address. The Validator below provides a simple check to see if the email address seems valid1. If the user's response doesn't contain an @ character with at least one word character on each side then the response is invalid and the user will have to enter an email address again (hopefully a valid one this time).

import re
from typing import List

import columbo


def is_email_address(value: str, _: columbo.Answers) -> columbo.ValidationResponse:
    if not re.match(r"^\w+@\w+", value):
        error_message = f"{value} is not a valid email address"
        return columbo.ValidationFailure(error=error_message)

    return columbo.ValidationSuccess()


interactions: List[columbo.Interaction] = [
    columbo.BasicQuestion(
        "user_email_address",
        "What email address should be used to contact you?",
        default="me@example.com",
        validator=is_email_address,
    )
]

user_answers = columbo.get_answers(interactions)
print(user_answers)

  1. The regular expression for checking for an RFC 822 compliant email address is overly complicated. Additionally, that only ensures that the text is valid. It does not confirm if the host will accept emails sent to that address or if the user is the owner of the email address.