| layout | default |
|---|---|
| title | Validators |
| nav_order | 3 |
A validator is any object with a validate(value) method that returns
None on success and raises ValidationError on failure. That is the entire
contract — user-defined validators are first-class.
from vcoder import Validator, MinLength, ValidationError
MinLength(5).validate("hello") # ok
MinLength(5).validate("hi") # raises ValidationErrorValidator(*children) composes validators and runs them in order, stopping at
the first failure. Because a composite is a validator, they nest freely.
from vcoder import Validator, MinLength, MaxLength, Regex, NoControlCharacters
password_rules = Validator(
MinLength(12),
MaxLength(128),
Regex(r".*[A-Z].*", full=True),
NoControlCharacters(),
)
password_rules.is_valid("Sup3rSecretPassphrase") # True/FalsePlain callables work too — anything callable(value) that raises
ValidationError:
def no_at_sign(value):
if "@" in value:
raise ValidationError("no @ allowed")
Validator(no_at_sign).validate("hello")| Validator | Checks |
|---|---|
Min(n) / Max(n) / Range(lo, hi) |
Ordered comparison bounds |
MinLength(n) / MaxLength(n) / Length(min, max, exact=) |
len(value) bounds |
Regex(pattern, flags=0, full=True) |
Regular-expression match |
NoControlCharacters() |
Rejects control characters |
Printable() |
Every character printable |
Ascii() |
Pure ASCII |
NoWhitespace() |
No whitespace characters |
Unicode(allow=, deny=) |
Restrict Unicode categories |
Entropy(min_bits, estimator=) |
Minimum estimated strength |
Unique() |
All elements distinct |
Blacklist(set, case_insensitive=) |
Value not in a forbidden set |
Whitelist(set, case_insensitive=) (alias OneOf) |
Value in an allowed set |
Predicate(func, message) |
Arbitrary boolean predicate |
Pass any validator to a prompt via validators=:
from vcoder import vc, Regex, NoControlCharacters
slug = vc.text(
"Slug: ",
validators=[Regex(r"[a-z0-9-]+"), NoControlCharacters()],
)Built-in prompt options (min, max, min_length, pattern, ...) are just
shortcuts that add the corresponding validators for you.
Subclass Validator and override validate:
from vcoder import Validator, ValidationError
class Even(Validator):
def validate(self, value):
if value % 2:
raise ValidationError("must be even", value=value)
vc.int("Even number: ", validators=[Even()])ValidationError stores the offending value on the exception object, but its
string form (used for reprompting and appearing in logs/tracebacks) never
includes the value. This keeps secrets out of your logs even when a password
fails validation. Keep this contract in your own validators: put context in the
message, put the raw value in value=.
Entropy(min_bits) uses a simple brute-force estimate by default. It is good
for catching obviously weak strings, not for precise strength scoring. To use a
better estimator (e.g. zxcvbn), pass estimator=:
from vcoder import Entropy
# def zxcvbn_bits(s: str) -> float: ...
Entropy(60, estimator=zxcvbn_bits)