formencode.validators
– lots of useful validators¶
Validator/Converters for use with FormEncode.
Module Contents¶
Basic Types¶
- class formencode.validators.ByteString(*args, **kw)¶
Convert to byte string, treating empty things as the empty string.
Also takes a max and min argument, and the string length must fall in that range.
Also you may give an encoding argument, which will encode any unicode that is found. Lists and tuples are joined with list_joiner (default
', '
) infrom_python
.>>> ByteString(min=2).to_python('a') Traceback (most recent call last): ... Invalid: Enter a value 2 characters long or more >>> ByteString(max=10).to_python('xxxxxxxxxxx') Traceback (most recent call last): ... Invalid: Enter a value not more than 10 characters long >>> ByteString().from_python(None) '' >>> ByteString().from_python([]) '' >>> ByteString().to_python(None) '' >>> ByteString(min=3).to_python(None) Traceback (most recent call last): ... Invalid: Please enter a value >>> ByteString(min=1).to_python('') Traceback (most recent call last): ... Invalid: Please enter a value
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
tooLong
:Enter a value not more than
%(max)i
characters longtooShort
:Enter a value
%(min)i
characters long or more
- class formencode.validators.StringBool(*args, **kw)¶
Converts a string to a boolean.
Values like ‘true’ and ‘false’ are considered True and False, respectively; anything in
true_values
is true, anything infalse_values
is false, case-insensitive). The first item of those lists is considered the preferred form.>>> s = StringBool() >>> s.to_python('yes'), s.to_python('no') (True, False) >>> s.to_python(1), s.to_python('N') (True, False) >>> s.to_python('ye') Traceback (most recent call last): ... Invalid: Value should be 'true' or 'false'
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
string
:Value should be
%(true)r
or%(false)r
- class formencode.validators.Bool(*args, **kw)¶
Always Valid, returns True or False based on the value and the existance of the value.
If you want to convert strings like
'true'
to booleans, then useStringBool
.Examples:
>>> Bool.to_python(0) False >>> Bool.to_python(1) True >>> Bool.to_python('') False >>> Bool.to_python(None) False
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.Int(*args, **kw)¶
Convert a value to an integer.
Example:
>>> Int.to_python('10') 10 >>> Int.to_python('ten') Traceback (most recent call last): ... Invalid: Please enter an integer value >>> Int(min=5).to_python('6') 6 >>> Int(max=10).to_python('11') Traceback (most recent call last): ... Invalid: Please enter a number that is 10 or smaller
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
integer
:Please enter an integer value
noneType
:The input must be a string (not None)
tooHigh
:Please enter a number that is
%(max)s
or smallertooLow
:Please enter a number that is
%(min)s
or greater
- class formencode.validators.Number(*args, **kw)¶
Convert a value to a float or integer.
Tries to convert it to an integer if no information is lost.
Example:
>>> Number.to_python('10') 10 >>> Number.to_python('10.5') 10.5 >>> Number.to_python('ten') Traceback (most recent call last): ... Invalid: Please enter a number >>> Number.to_python([1.2]) Traceback (most recent call last): ... Invalid: Please enter a number >>> Number(min=5).to_python('6.5') 6.5 >>> Number(max=10.5).to_python('11.5') Traceback (most recent call last): ... Invalid: Please enter a number that is 10.5 or smaller
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
number
:Please enter a number
tooHigh
:Please enter a number that is
%(max)s
or smallertooLow
:Please enter a number that is
%(min)s
or greater
- class formencode.validators.UnicodeString(**kw)¶
Convert things to unicode string.
This is implemented as a specialization of the ByteString class.
You can also use the alias String for this validator.
In addition to the String arguments, an encoding argument is also accepted. By default, the encoding will be utf-8. You can overwrite this using the encoding parameter. You can also set inputEncoding and outputEncoding differently. An inputEncoding of None means “do not decode”, an outputEncoding of None means “do not encode”.
All converted strings are returned as Unicode strings.
>>> UnicodeString().to_python(None) == '' True >>> UnicodeString().to_python([]) == '' True >>> UnicodeString(encoding='utf-7').to_python('Ni Ni Ni') == 'Ni Ni Ni' True
Messages
badEncoding
:Invalid data or incorrect encoding
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
tooLong
:Enter a value not more than
%(max)i
characters longtooShort
:Enter a value
%(min)i
characters long or more
- class formencode.validators.Set(*args, **kw)¶
This is for when you think you may return multiple values for a certain field.
This way the result will always be a list, even if there’s only one result. It’s equivalent to ForEach(convert_to_list=True).
If you give
use_set=True
, then it will return an actualset
object.>>> Set.to_python(None) [] >>> Set.to_python('this') ['this'] >>> Set.to_python(('this', 'that')) ['this', 'that'] >>> s = Set(use_set=True) >>> s.to_python(None) set() >>> s.to_python('this') {'this'} >>> s.to_python(('this',)) {'this'}
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
Basic Validator/Converters¶
- class formencode.validators.ConfirmType(*args, **kw)¶
Confirms that the input/output is of the proper type.
Uses the parameters:
- subclass:
The class or a tuple of classes; the item must be an instance of the class or a subclass.
- type:
A type or tuple of types (or classes); the item must be of the exact class or type. Subclasses are not allowed.
Examples:
>>> cint = ConfirmType(subclass=int) >>> cint.to_python(True) True >>> cint.to_python('1') Traceback (most recent call last): ... Invalid: '1' is not a subclass of <type 'int'> >>> cintfloat = ConfirmType(subclass=(float, int)) >>> cintfloat.to_python(1.0), cintfloat.from_python(1.0) (1.0, 1.0) >>> cintfloat.to_python(1), cintfloat.from_python(1) (1, 1) >>> cintfloat.to_python(None) Traceback (most recent call last): ... Invalid: None is not a subclass of one of the types <type 'float'>, <type 'int'> >>> cint2 = ConfirmType(type=int) >>> cint2(accept_python=False).from_python(True) Traceback (most recent call last): ... Invalid: True must be of the type <type 'int'>
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
inSubclass
:%(object)r
is not a subclass of one of the types%(subclassList)s
inType
:%(object)r
must be one of the types%(typeList)s
noneType
:The input must be a string (not None)
subclass
:%(object)r
is not a subclass of%(subclass)s
type
:%(object)r
must be of the type%(type)s
- class formencode.validators.Wrapper(*args, **kw)¶
Used to convert functions to validator/converters.
You can give a simple function for _convert_to_python, _convert_from_python, _validate_python or _validate_other. If that function raises an exception, the value is considered invalid. Whatever value the function returns is considered the converted value.
Unlike validators, the state argument is not used. Functions like int can be used here, that take a single argument.
Note that as Wrapper will generate a FancyValidator, empty values (those who pass
FancyValidator.is_empty)
will returnNone
. To override this behavior you can useWrapper(empty_value=callable)
. For example passingWrapper(empty_value=lambda val: val)
will return the value itself when is considered empty.Examples:
>>> def downcase(v): ... return v.lower() >>> wrap = Wrapper(convert_to_python=downcase) >>> wrap.to_python('This') 'this' >>> wrap.from_python('This') 'This' >>> wrap.to_python('') is None True >>> wrap2 = Wrapper( ... convert_from_python=downcase, empty_value=lambda value: value) >>> wrap2.from_python('This') 'this' >>> wrap2.to_python('') '' >>> wrap2.from_python(1) Traceback (most recent call last): ... Invalid: 'int' object has no attribute 'lower' >>> wrap3 = Wrapper(validate_python=int) >>> wrap3.to_python('1') '1' >>> wrap3.to_python('a') Traceback (most recent call last): ... Invalid: invalid literal for int()...
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.Constant(*args, **kw)¶
This converter converts everything to the same thing.
I.e., you pass in the constant value when initializing, then all values get converted to that constant value.
This is only really useful for funny situations, like:
# Any evaluates sub validators in reverse order for to_python fromEmailValidator = Any( Constant('unknown@localhost'), Email())
In this case, the if the email is not valid
'unknown@localhost'
will be used instead. Of course, you could useif_invalid
instead.Examples:
>>> Constant('X').to_python('y') 'X'
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.StripField(*args, **kw)¶
Take a field from a dictionary, removing the key from the dictionary.
name
is the key. The field value and a new copy of the dictionary with that field removed are returned.>>> StripField('test').to_python({'a': 1, 'test': 2}) (2, {'a': 1}) >>> StripField('test').to_python({}) Traceback (most recent call last): ... Invalid: The name 'test' is missing
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
missing
:The name
%(name)s
is missingnoneType
:The input must be a string (not None)
- class formencode.validators.OneOf(*args, **kw)¶
Tests that the value is one of the members of a given list.
If
testValueList=True
, then if the input value is a list or tuple, all the members of the sequence will be checked (i.e., the input must be a subset of the allowed values).Use
hideList=True
to keep the list of valid values out of the error message in exceptions.Examples:
>>> oneof = OneOf([1, 2, 3]) >>> oneof.to_python(1) 1 >>> oneof.to_python(4) Traceback (most recent call last): ... Invalid: Value must be one of: 1; 2; 3 (not 4) >>> oneof(testValueList=True).to_python([2, 3, [1, 2, 3]]) [2, 3, [1, 2, 3]] >>> oneof.to_python([2, 3, [1, 2, 3]]) Traceback (most recent call last): ... Invalid: Value must be one of: 1; 2; 3 (not [2, 3, [1, 2, 3]])
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:Invalid value
noneType
:The input must be a string (not None)
notIn
:Value must be one of:
%(items)s
(not%(value)r
)
- class formencode.validators.DictConverter(*args, **kw)¶
Converts values based on a dictionary which has values as keys for the resultant values.
If
allowNull
is passed, it will not balk if a false value (e.g., ‘’ or None) is given (it will return None in these cases).to_python takes keys and gives values, from_python takes values and gives keys.
If you give hideDict=True, then the contents of the dictionary will not show up in error messages.
Examples:
>>> dc = DictConverter({1: 'one', 2: 'two'}) >>> dc.to_python(1) 'one' >>> dc.from_python('one') 1 >>> dc.to_python(3) Traceback (most recent call last): .... Invalid: Enter a value from: 1; 2 >>> dc2 = dc(hideDict=True) >>> dc2.hideDict True >>> dc2.dict {1: 'one', 2: 'two'} >>> dc2.to_python(3) Traceback (most recent call last): .... Invalid: Choose something >>> dc.from_python('three') Traceback (most recent call last): .... Invalid: Nothing in my dictionary goes by the value 'three'. Choose one of: 'one'; 'two'
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)chooseKey
:Enter a value from:
%(items)s
chooseValue
:Nothing in my dictionary goes by the value
%(value)s
. Choose one of:%(items)s
empty
:Please enter a value
keyNotFound
:Choose something
noneType
:The input must be a string (not None)
valueNotFound
:That value is not known
- class formencode.validators.IndexListConverter(*args, **kw)¶
Converts a index (which may be a string like ‘2’) to the value in the given list.
Examples:
>>> index = IndexListConverter(['zero', 'one', 'two']) >>> index.to_python(0) 'zero' >>> index.from_python('zero') 0 >>> index.to_python('1') 'one' >>> index.to_python(5) Traceback (most recent call last): Invalid: Index out of range >>> index(not_empty=True).to_python(None) Traceback (most recent call last): Invalid: Please enter a value >>> index.from_python('five') Traceback (most recent call last): Invalid: Item 'five' was not found in the list
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
integer
:Must be an integer index
noneType
:The input must be a string (not None)
notFound
:Item
%(value)s
was not found in the listoutOfRange
:Index out of range
Simple Validators¶
- class formencode.validators.MaxLength(*args, **kw)¶
Invalid if the value is longer than maxLength. Uses len(), so it can work for strings, lists, or anything with length.
Examples:
>>> max5 = MaxLength(5) >>> max5.to_python('12345') '12345' >>> max5.from_python('12345') '12345' >>> max5.to_python('123456') Traceback (most recent call last): ... Invalid: Enter a value less than 5 characters long >>> max5(accept_python=False).from_python('123456') Traceback (most recent call last): ... Invalid: Enter a value less than 5 characters long >>> max5.to_python([1, 2, 3]) [1, 2, 3] >>> max5.to_python([1, 2, 3, 4, 5, 6]) Traceback (most recent call last): ... Invalid: Enter a value less than 5 characters long >>> max5.to_python(5) Traceback (most recent call last): ... Invalid: Invalid value (value with length expected)
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:Invalid value (value with length expected)
noneType
:The input must be a string (not None)
tooLong
:Enter a value less than
%(maxLength)i
characters long
- class formencode.validators.MinLength(*args, **kw)¶
Invalid if the value is shorter than minlength. Uses len(), so it can work for strings, lists, or anything with length. Note that you must use
not_empty=True
if you don’t want to accept empty values – empty values are not tested for length.Examples:
>>> min5 = MinLength(5) >>> min5.to_python('12345') '12345' >>> min5.from_python('12345') '12345' >>> min5.to_python('1234') Traceback (most recent call last): ... Invalid: Enter a value at least 5 characters long >>> min5(accept_python=False).from_python('1234') Traceback (most recent call last): ... Invalid: Enter a value at least 5 characters long >>> min5.to_python([1, 2, 3, 4, 5]) [1, 2, 3, 4, 5] >>> min5.to_python([1, 2, 3]) Traceback (most recent call last): ... Invalid: Enter a value at least 5 characters long >>> min5.to_python(5) Traceback (most recent call last): ... Invalid: Invalid value (value with length expected)
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:Invalid value (value with length expected)
noneType
:The input must be a string (not None)
tooShort
:Enter a value at least
%(minLength)i
characters long
- class formencode.validators.NotEmpty(*args, **kw)¶
Invalid if value is empty (empty string, empty list, etc).
Generally for objects that Python considers false, except zero which is not considered invalid.
Examples:
>>> ne = NotEmpty(messages=dict(empty='enter something')) >>> ne.to_python('') Traceback (most recent call last): ... Invalid: enter something >>> ne.to_python(0) 0
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.Empty(*args, **kw)¶
Invalid unless the value is empty. Use cleverly, if at all.
Examples:
>>> Empty.to_python(0) Traceback (most recent call last): ... Invalid: You cannot enter a value here
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
notEmpty
:You cannot enter a value here
- class formencode.validators.Regex(*args, **kw)¶
Invalid if the value doesn’t match the regular expression regex.
The regular expression can be a compiled re object, or a string which will be compiled for you.
Use strip=True if you want to strip the value before validation, and as a form of conversion (often useful).
Examples:
>>> cap = Regex(r'^[A-Z]+$') >>> cap.to_python('ABC') 'ABC'
Note that
.from_python()
calls (in general) do not validate the input:>>> cap.from_python('abc') 'abc' >>> cap(accept_python=False).from_python('abc') Traceback (most recent call last): ... Invalid: The input is not valid >>> cap.to_python(1) Traceback (most recent call last): ... Invalid: The input must be a string (not a <type 'int'>: 1) >>> Regex(r'^[A-Z]+$', strip=True).to_python(' ABC ') 'ABC' >>> Regex(r'this', regexOps=('I',)).to_python('THIS') 'THIS'
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:The input is not valid
noneType
:The input must be a string (not None)
- class formencode.validators.PlainText(*args, **kw)¶
Test that the field contains only letters, numbers, underscore, and the hyphen. Subclasses Regex.
Examples:
>>> PlainText.to_python('_this9_') '_this9_' >>> PlainText.from_python(' this ') ' this ' >>> PlainText(accept_python=False).from_python(' this ') Traceback (most recent call last): ... Invalid: Enter only letters, numbers, - (hyphen) or _ (underscore) >>> PlainText(strip=True).to_python(' this ') 'this' >>> PlainText(strip=True).from_python(' this ') 'this'
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:Enter only letters, numbers, - (hyphen) or _ (underscore)
noneType
:The input must be a string (not None)
Dates and Times¶
- class formencode.validators.DateValidator(*args, **kw)¶
Validates that a date is within the given range. Be sure to call DateConverter first if you aren’t expecting mxDateTime input.
earliest_date
andlatest_date
may be functions; if so, they will be called each time before validating.after_now
means a time after the current timestamp; note that just a few milliseconds before now is invalid!today_or_after
is more permissive, and ignores hours and minutes.Examples:
>>> from datetime import datetime, timedelta >>> d = DateValidator(earliest_date=datetime(2003, 1, 1)) >>> d.to_python(datetime(2004, 1, 1)) datetime.datetime(2004, 1, 1, 0, 0) >>> d.to_python(datetime(2002, 1, 1)) Traceback (most recent call last): ... Invalid: Date must be after Wednesday, 01 January 2003 >>> d.to_python(datetime(2003, 1, 1)) datetime.datetime(2003, 1, 1, 0, 0) >>> d = DateValidator(after_now=True) >>> now = datetime.now() >>> d.to_python(now+timedelta(seconds=5)) == now+timedelta(seconds=5) True >>> d.to_python(now-timedelta(days=1)) Traceback (most recent call last): ... Invalid: The date must be sometime in the future >>> d.to_python(now+timedelta(days=1)) > now True >>> d = DateValidator(today_or_after=True) >>> d.to_python(now) == now True
Messages
after
:Date must be after
%(date)s
badType
:The input must be a string (not a
%(type)s
:%(value)r
)before
:Date must be before
%(date)s
date_format
:%%A, %%d %%B %%Y
empty
:Please enter a value
future
:The date must be sometime in the future
noneType
:The input must be a string (not None)
- class formencode.validators.DateConverter(*args, **kw)¶
Validates and converts a string date, like mm/yy, dd/mm/yy, dd-mm-yy, etc. Using
month_style
you can support the three general stylesmdy
=us
=mm/dd/yyyy
,dmy
=euro
=dd/mm/yyyy
andymd
=iso
=yyyy/mm/dd
.Accepts English month names, also abbreviated. Returns value as a datetime object (you can get mx.DateTime objects if you use
datetime_module='mxDateTime'
). Two year dates are assumed to be within 1950-2020, with dates from 21-49 being ambiguous and signaling an error.Use accept_day=False if you just want a month/year (like for a credit card expiration date).
>>> d = DateConverter() >>> d.to_python('12/3/09') datetime.date(2009, 12, 3) >>> d.to_python('12/3/2009') datetime.date(2009, 12, 3) >>> d.to_python('2/30/04') Traceback (most recent call last): ... Invalid: That month only has 29 days >>> d.to_python('13/2/05') Traceback (most recent call last): ... Invalid: Please enter a month from 1 to 12 >>> d.to_python('1/1/200') Traceback (most recent call last): ... Invalid: Please enter a four-digit year after 1899
If you change
month_style
you can get European-style dates:>>> d = DateConverter(month_style='dd/mm/yyyy') >>> date = d.to_python('12/3/09') >>> date datetime.date(2009, 3, 12) >>> d.from_python(date) '12/03/2009'
Messages
badFormat
:Please enter the date in the form
%(format)s
badType
:The input must be a string (not a
%(type)s
:%(value)r
)dayRange
:That month only has
%(days)i
daysempty
:Please enter a value
fourDigitYear
:Please enter a four-digit year after 1899
invalidDate
:That is not a valid day (
%(exception)s
)invalidDay
:Please enter a valid day
invalidYear
:Please enter a number for the year
monthRange
:Please enter a month from 1 to 12
noneType
:The input must be a string (not None)
unknownMonthName
:Unknown month name:
%(month)s
wrongFormat
:Please enter the date in the form
%(format)s
- class formencode.validators.TimeConverter(*args, **kw)¶
Converts times in the format HH:MM:SSampm to (h, m, s). Seconds are optional.
For ampm, set use_ampm = True. For seconds, use_seconds = True. Use ‘optional’ for either of these to make them optional.
Examples:
>>> tim = TimeConverter() >>> tim.to_python('8:30') (8, 30) >>> tim.to_python('20:30') (20, 30) >>> tim.to_python('30:00') Traceback (most recent call last): ... Invalid: You must enter an hour in the range 0-23 >>> tim.to_python('13:00pm') Traceback (most recent call last): ... Invalid: You must enter an hour in the range 1-12 >>> tim.to_python('12:-1') Traceback (most recent call last): ... Invalid: You must enter a minute in the range 0-59 >>> tim.to_python('12:02pm') (12, 2) >>> tim.to_python('12:02am') (0, 2) >>> tim.to_python('1:00PM') (13, 0) >>> tim.from_python((13, 0)) '13:00:00' >>> tim2 = tim(use_ampm=True, use_seconds=False) >>> tim2.from_python((13, 0)) '1:00pm' >>> tim2.from_python((0, 0)) '12:00am' >>> tim2.from_python((12, 0)) '12:00pm'
Examples with
datetime.time
:>>> v = TimeConverter(use_datetime=True) >>> a = v.to_python('18:00') >>> a datetime.time(18, 0) >>> b = v.to_python('30:00') Traceback (most recent call last): ... Invalid: You must enter an hour in the range 0-23 >>> v2 = TimeConverter(prefer_ampm=True, use_datetime=True) >>> v2.from_python(a) '6:00:00pm' >>> v3 = TimeConverter(prefer_ampm=True, ... use_seconds=False, use_datetime=True) >>> a = v3.to_python('18:00') >>> a datetime.time(18, 0) >>> v3.from_python(a) '6:00pm' >>> a = v3.to_python('18:00:00') Traceback (most recent call last): ... Invalid: You may not enter seconds
Messages
badHour
:You must enter an hour in the range
%(range)s
badMinute
:You must enter a minute in the range 0-59
badNumber
:The
%(part)s
value you gave is not a number:%(number)r
badSecond
:You must enter a second in the range 0-59
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
minutesRequired
:You must enter minutes (after a :)
noAMPM
:You must indicate AM or PM
noSeconds
:You may not enter seconds
noneType
:The input must be a string (not None)
secondsRequired
:You must enter seconds
tooManyColon
:There are too many :’s
HTML Form Helpers¶
- class formencode.validators.SignedString(*args, **kw)¶
Encodes a string into a signed string, and base64 encodes both the signature string and a random nonce.
It is up to you to provide a secret, and to keep the secret handy and consistent.
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)badsig
:Signature is not correct
empty
:Please enter a value
malformed
:Value does not contain a signature
noneType
:The input must be a string (not None)
- class formencode.validators.FieldStorageUploadConverter(*args, **kw)¶
Handles cgi.FieldStorage instances that are file uploads.
This doesn’t do any conversion, but it can detect empty upload fields (which appear like normal fields, but have no filename when no upload was given).
Requires the legacy-cgi package on Python 3.13 and later.
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.FileUploadKeeper(*args, **kw)¶
Takes two inputs (a dictionary with keys
static
andupload
) and converts them into one value on the Python side (a dictionary withfilename
andcontent
keys). The upload takes priority over the static value. The filename may be None if it can’t be discovered.Handles uploads of both text and
cgi.FieldStorage
upload values.This is basically for use when you have an upload field, and you want to keep the upload around even if the rest of the form submission fails. When converting back to the form submission, there may be extra values
'original_filename'
and'original_content'
, which may want to use in your form to show the user you still have their content around.To use this, make sure you are using variabledecode, then use something like:
<input type="file" name="myfield.upload"> <input type="hidden" name="myfield.static">
Then in your scheme:
class MyScheme(Scheme): myfield = FileUploadKeeper()
Note that big file uploads mean big hidden fields, and lots of bytes passed back and forth in the case of an error.
Note: requires the legacy-cgi package on Python 3.13 and later to be able to handle
cgi.FieldStorage
values.Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
URLs, Email, etc.¶
- class formencode.validators.Email(*args, **kw)¶
Validate an email address.
If you pass
resolve_domain=True
, then it will try to resolve the domain name to make sure it’s valid. This takes longer, of course. You must have the dnspython modules installed to look up DNS (MX and A) records.>>> e = Email() >>> e.to_python(' test@foo.com ') 'test@foo.com' >>> e.to_python('test') Traceback (most recent call last): ... Invalid: An email address must contain a single @ >>> e.to_python('test@foobar') Traceback (most recent call last): ... Invalid: The domain portion of the email address is invalid (the portion after the @: foobar) >>> e.to_python('test@foobar.com.5') Traceback (most recent call last): ... Invalid: The domain portion of the email address is invalid (the portion after the @: foobar.com.5) >>> e.to_python('test@foo..bar.com') Traceback (most recent call last): ... Invalid: The domain portion of the email address is invalid (the portion after the @: foo..bar.com) >>> e.to_python('test@.foo.bar.com') Traceback (most recent call last): ... Invalid: The domain portion of the email address is invalid (the portion after the @: .foo.bar.com) >>> e.to_python('nobody@xn--m7r7ml7t24h.com') 'nobody@xn--m7r7ml7t24h.com' >>> e.to_python('o*reilly@test.com') 'o*reilly@test.com' >>> e = Email(resolve_domain=True) >>> e.resolve_domain True >>> e.to_python('doesnotexist@colorstudy.com') 'doesnotexist@colorstudy.com' >>> e.to_python('test@nyu.edu') 'test@nyu.edu' >>> # NOTE: If you do not have dnspython installed this example won't work: >>> e.to_python('test@thisdomaindoesnotexistithinkforsure.com') Traceback (most recent call last): ... Invalid: The domain of the email address does not exist (the portion after the @: thisdomaindoesnotexistithinkforsure.com) >>> e.to_python('test@google.com') 'test@google.com' >>> e = Email(not_empty=False) >>> e.to_python('')
Messages
badDomain
:The domain portion of the email address is invalid (the portion after the @:
%(domain)s
)badType
:The input must be a string (not a
%(type)s
:%(value)r
)badUsername
:The username portion of the email address is invalid (the portion before the @:
%(username)s
)domainDoesNotExist
:The domain of the email address does not exist (the portion after the @:
%(domain)s
)empty
:Please enter an email address
noAt
:An email address must contain a single @
noneType
:The input must be a string (not None)
socketError
:An error occured when trying to connect to the server:
%(error)s
- class formencode.validators.URL(*args, **kw)¶
Validate a URL, either http://… or https://. If check_exists is true, then we’ll actually make a request for the page.
If add_http is true, then if no scheme is present we’ll add http://
>>> u = URL(add_http=True) >>> u.to_python('foo.com') 'http://foo.com' >>> u.to_python('http://hahaha.ha/bar.html') 'http://hahaha.ha/bar.html' >>> u.to_python('http://xn--m7r7ml7t24h.com') 'http://xn--m7r7ml7t24h.com' >>> u.to_python('http://xn--c1aay4a.xn--p1ai') 'http://xn--c1aay4a.xn--p1ai' >>> u.to_python('http://foo.com/test?bar=baz&fleem=morx') 'http://foo.com/test?bar=baz&fleem=morx' >>> u.to_python('http://foo.com/login?came_from=http%3A%2F%2Ffoo.com%2Ftest') 'http://foo.com/login?came_from=http%3A%2F%2Ffoo.com%2Ftest' >>> u.to_python('http://foo.com:8000/test.html') 'http://foo.com:8000/test.html' >>> u.to_python('http://foo.com/something\\nelse') Traceback (most recent call last): ... Invalid: That is not a valid URL >>> u.to_python('https://test.com') 'https://test.com' >>> u.to_python('http://test') Traceback (most recent call last): ... Invalid: You must provide a full domain name (like test.com) >>> u.to_python('http://test..com') Traceback (most recent call last): ... Invalid: That is not a valid URL >>> u = URL(add_http=False, check_exists=True) >>> u.to_python('http://google.com') 'http://google.com' >>> u.to_python('google.com') Traceback (most recent call last): ... Invalid: You must start your URL with http://, https://, etc >>> u.to_python('https://httpbin.org/status/404') Traceback (most recent call last): ... Invalid: The server responded that the page could not be found >>> u.to_python('http://this.domain.does.not.exist.example.org/test.html') ... Traceback (most recent call last): ... Invalid: An error occured when trying to connect to the server: ...
If you want to allow addresses without a TLD (e.g.,
localhost
) you can do:>>> URL(require_tld=False).to_python('http://localhost') 'http://localhost'
By default, internationalized domain names (IDNA) in Unicode will be accepted and encoded to ASCII using Punycode (as described in RFC 3490). You may set allow_idna to False to change this behavior:
>>> URL(allow_idna=True).to_python( ... 'http://\u0433\u0443\u0433\u043b.\u0440\u0444') 'http://xn--c1aay4a.xn--p1ai' >>> URL(allow_idna=True, add_http=True).to_python( ... '\u0433\u0443\u0433\u043b.\u0440\u0444') 'http://xn--c1aay4a.xn--p1ai' >>> URL(allow_idna=False).to_python( ... 'http://\u0433\u0443\u0433\u043b.\u0440\u0444') Traceback (most recent call last): ... Invalid: That is not a valid URL
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)badURL
:That is not a valid URL
empty
:Please enter a value
httpError
:An error occurred when trying to access the URL:
%(error)s
noScheme
:noTLD
:You must provide a full domain name (like
%(domain)s
.com)noneType
:The input must be a string (not None)
notFound
:The server responded that the page could not be found
socketError
:An error occured when trying to connect to the server:
%(error)s
status
:The server responded with a bad status code (
%(status)s
)
- class formencode.validators.IPAddress(*args, **kw)¶
Formencode validator to check whether a string is a correct IP address.
Examples:
>>> ip = IPAddress() >>> ip.to_python('127.0.0.1') '127.0.0.1' >>> ip.to_python('299.0.0.1') Traceback (most recent call last): ... Invalid: The octets must be within the range of 0-255 (not '299') >>> ip.to_python('192.168.0.1/1') Traceback (most recent call last): ... Invalid: Please enter a valid IP address (a.b.c.d) >>> ip.to_python('asdf') Traceback (most recent call last): ... Invalid: Please enter a valid IP address (a.b.c.d)
Messages
badFormat
:Please enter a valid IP address (a.b.c.d)
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
illegalOctets
:The octets must be within the range of 0-255 (not
%(octet)r
)leadingZeros
:The octets must not have leading zeros
noneType
:The input must be a string (not None)
- class formencode.validators.CIDR(*args, **kw)¶
Formencode validator to check whether a string is in correct CIDR notation (IP address, or IP address plus /mask).
Examples:
>>> cidr = CIDR() >>> cidr.to_python('127.0.0.1') '127.0.0.1' >>> cidr.to_python('299.0.0.1') Traceback (most recent call last): ... Invalid: The octets must be within the range of 0-255 (not '299') >>> cidr.to_python('192.168.0.1/1') Traceback (most recent call last): ... Invalid: The network size (bits) must be within the range of 8-32 (not '1') >>> cidr.to_python('asdf') Traceback (most recent call last): ... Invalid: Please enter a valid IP address (a.b.c.d) or IP network (a.b.c.d/e)
Messages
badFormat
:Please enter a valid IP address (a.b.c.d) or IP network (a.b.c.d/e)
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
illegalBits
:The network size (bits) must be within the range of 8-32 (not
%(bits)r
)illegalOctets
:The octets must be within the range of 0-255 (not
%(octet)r
)leadingZeros
:The octets must not have leading zeros
noneType
:The input must be a string (not None)
- class formencode.validators.MACAddress(*args, **kw)¶
Formencode validator to check whether a string is a correct hardware (MAC) address.
Examples:
>>> mac = MACAddress() >>> mac.to_python('aa:bb:cc:dd:ee:ff') 'aabbccddeeff' >>> mac.to_python('aa:bb:cc:dd:ee:ff:e') Traceback (most recent call last): ... Invalid: A MAC address must contain 12 digits and A-F; the value you gave has 13 characters >>> mac.to_python('aa:bb:cc:dd:ee:fx') Traceback (most recent call last): ... Invalid: MAC addresses may only contain 0-9 and A-F (and optionally :), not 'x' >>> MACAddress(add_colons=True).to_python('aabbccddeeff') 'aa:bb:cc:dd:ee:ff'
Messages
badCharacter
:MAC addresses may only contain 0-9 and A-F (and optionally :), not
%(char)r
badLength
:A MAC address must contain 12 digits and A-F; the value you gave has
%(length)s
charactersbadType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
Form-wide Validation¶
- class formencode.validators.FormValidator(*args, **kw)¶
A FormValidator is something that can be chained with a Schema.
Unlike normal chaining the FormValidator can validate forms that aren’t entirely valid.
The important method is .validate(), of course. It gets passed a dictionary of the (processed) values from the form. If you have .validate_partial_form set to True, then it will get the incomplete values as well – check with the “in” operator if the form was able to process any particular field.
Anyway, .validate() should return a string or a dictionary. If a string, it’s an error message that applies to the whole form. If not, then it should be a dictionary of fieldName: errorMessage. The special key “form” is the error message for the form as a whole (i.e., a string is equivalent to {“form”: string}).
Returns None on no errors.
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.RequireIfMissing(*args, **kw)¶
Require one field based on another field being present or missing.
This validator is applied to a form, not an individual field (usually using a Schema’s
pre_validators
orchained_validators
) and is available under both namesRequireIfMissing
andRequireIfPresent
.If you provide a
missing
value (a string key name) then if that field is missing the field must be entered. This gives you an either/or situation.If you provide a
present
value (another string key name) then if that field is present, the required field must also be present.>>> from formencode import validators >>> v = validators.RequireIfPresent('phone_type', present='phone') >>> v.to_python(dict(phone_type='', phone='510 420 4577')) Traceback (most recent call last): ... Invalid: You must give a value for phone_type >>> v.to_python(dict(phone='')) {'phone': ''}
Note that if you have a validator on the optionally-required field, you should probably use
if_missing=None
. This way you won’t get an error from the Schema about a missing value. For example:class PhoneInput(Schema): phone = PhoneNumber() phone_type = String(if_missing=None) chained_validators = [RequireIfPresent('phone_type', present='phone')]
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.RequireIfMatching(*args, **kw)¶
Require a list of fields based on the value of another field.
This validator is applied to a form, not an individual field (usually using a Schema’s
pre_validators
orchained_validators
).You provide a field name, an expected value and a list of required fields (a list of string key names). If the value of the field, if present, matches the value of
expected_value
, then the validator will raise anInvalid
exception for every field inrequired_fields
that is missing.>>> from formencode import validators >>> v = validators.RequireIfMatching('phone_type', expected_value='mobile', required_fields=['mobile']) >>> v.to_python(dict(phone_type='mobile')) Traceback (most recent call last): ... Invalid: You must give a value for mobile >>> v.to_python(dict(phone_type='someothervalue')) {'phone_type': 'someothervalue'}
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
- class formencode.validators.FieldsMatch(*args, **kw)¶
Tests that the given fields match, i.e., are identical. Useful for password+confirmation fields. Pass the list of field names in as field_names.
>>> f = FieldsMatch('pass', 'conf') >>> sorted(f.to_python({'pass': 'xx', 'conf': 'xx'}).items()) [('conf', 'xx'), ('pass', 'xx')] >>> f.to_python({'pass': 'xx', 'conf': 'yy'}) Traceback (most recent call last): ... Invalid: conf: Fields do not match
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalid
:Fields do not match (should be
%(match)s
)invalidNoMatch
:Fields do not match
noneType
:The input must be a string (not None)
notDict
:Fields should be a dictionary
Credit Cards¶
- class formencode.validators.CreditCardValidator(*args, **kw)¶
Checks that credit card numbers are valid (if not real).
You pass in the name of the field that has the credit card type and the field with the credit card number. The credit card type should be one of “visa”, “mastercard”, “amex”, “dinersclub”, “discover”, “jcb”.
You must check the expiration date yourself (there is no relation between CC number/types and expiration dates).
>>> cc = CreditCardValidator() >>> sorted(cc.to_python({'ccType': 'visa', 'ccNumber': '4111111111111111'}).items()) [('ccNumber', '4111111111111111'), ('ccType', 'visa')] >>> cc.to_python({'ccType': 'visa', 'ccNumber': '411111111111111'}) Traceback (most recent call last): ... Invalid: ccNumber: You did not enter a valid number of digits >>> cc.to_python({'ccType': 'visa', 'ccNumber': '411111111111112'}) Traceback (most recent call last): ... Invalid: ccNumber: You did not enter a valid number of digits >>> cc().to_python({}) Traceback (most recent call last): ... Invalid: The field ccType is missing
Messages
badLength
:You did not enter a valid number of digits
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalidNumber
:That number is not valid
missing_key
:The field
%(key)s
is missingnoneType
:The input must be a string (not None)
notANumber
:Please enter only the number, no other characters
- class formencode.validators.CreditCardExpires(*args, **kw)¶
Checks that credit card expiration date is valid relative to the current date.
You pass in the name of the field that has the credit card expiration month and the field with the credit card expiration year.
>>> ed = CreditCardExpires() >>> sorted(ed.to_python({'ccExpiresMonth': '11', 'ccExpiresYear': '2250'}).items()) [('ccExpiresMonth', '11'), ('ccExpiresYear', '2250')] >>> ed.to_python({'ccExpiresMonth': '10', 'ccExpiresYear': '2005'}) Traceback (most recent call last): ... Invalid: ccExpiresMonth: Invalid Expiration Date<br> ccExpiresYear: Invalid Expiration Date
Messages
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
invalidNumber
:Invalid Expiration Date
noneType
:The input must be a string (not None)
notANumber
:Please enter numbers only for month and year
- class formencode.validators.CreditCardSecurityCode(*args, **kw)¶
Checks that credit card security code has the correct number of digits for the given credit card type.
You pass in the name of the field that has the credit card type and the field with the credit card security code.
>>> code = CreditCardSecurityCode() >>> sorted(code.to_python({'ccType': 'visa', 'ccCode': '111'}).items()) [('ccCode', '111'), ('ccType', 'visa')] >>> code.to_python({'ccType': 'visa', 'ccCode': '1111'}) Traceback (most recent call last): ... Invalid: ccCode: Invalid credit card security code length
Messages
badLength
:Invalid credit card security code length
badType
:The input must be a string (not a
%(type)s
:%(value)r
)empty
:Please enter a value
noneType
:The input must be a string (not None)
notANumber
:Please enter numbers only for credit card security code