Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It would be great if validators.regexp could use re.fullmatch #867

Open
dougthor42 opened this issue Nov 5, 2024 · 1 comment
Open

It would be great if validators.regexp could use re.fullmatch #867

dougthor42 opened this issue Nov 5, 2024 · 1 comment

Comments

@dougthor42
Copy link

dougthor42 commented Nov 5, 2024

The regexp validator uses re.match:

match = self.regex.match(field.data or "")

This means that it's not trivial to ensure that the entire string matches a regex, especially when that regex is complex.

I propose something like this:

class Regexp:
    """
    Validates the field against a user provided regexp.

    :param regex:
        The regular expression string to use. Can also be a compiled regular
        expression pattern.
    :param flags:
        The regexp flags to use, for example re.IGNORECASE. Ignored if
        `regex` is not a string.
    :param message:
        Error message to raise in case of a validation error.
    :param re_match_type
        "match" (default), "fullmatch", or "search"
    """

    def __init__(self, regex, flags=0, message=None, re_match_type="match":
        if isinstance(regex, str):
            regex = re.compile(regex, flags)
        self.regex = regex
        self.message = message
        self.re_match_type = re_match_type

    def __call__(self, form, field, message=None):
        if self.re_match_type == "match":
            match = self.regex.match(field.data or "")
        if self.re_match_type == "fullmatch":
            match = self.regex.fullmatch(field.data or "")
        elif self.re_match_type == "search":
            match = self.regex.search(field.data or "")
        else:
            raise ValueError("... but how???")
            
        if match:
            return match

        if message is None:
            if self.message is None:
                message = field.gettext("Invalid input.")
            else:
                message = self.message

        raise ValidationError(message)

Obviously I could make it more "intelligent" with getattr or something, and a real implementation would probably use an enum and do the validation elsewhere, but for the purposes of getting the idea across, the above is sufficient.

Thoughts? Would you mind if I implemented this?

Current workaround:

Make a custom validator akin to:

def validate_regexp_fullmatch(regex: str | re.Pattern) -> Callable:
    """A validator very similar to `wtforms.validators.regexp`, except that it uses 'fullmatch'."""
    message = "Regex Match failure"
    if isinstance(regex, str):
        regex = re.compile(regex)

    def _validate(form, field):
        match = regex.fullmatch(field.data or "")
        if match:
            return match

        raise wtforms.validators.ValidationError(message)

    return _validate

Environment

  • Python version: 3.12
  • wtforms version: 3.1.2
@artempronevskiy
Copy link

#871

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants