mirror of
https://github.com/djohnlewis/stackdump
synced 2025-12-07 00:13:33 +00:00
Initial commit. Still building up the env and some parsing code.
This commit is contained in:
151
python/packages/formencode/foreach.py
Normal file
151
python/packages/formencode/foreach.py
Normal file
@@ -0,0 +1,151 @@
|
||||
"""
|
||||
Validator for repeating items.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
try:
|
||||
set
|
||||
except NameError: # Python < 2.4
|
||||
from sets import Set as set
|
||||
|
||||
filters = warnings.filters[:]
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
warnings.filters = filters
|
||||
|
||||
|
||||
from api import NoDefault, Invalid
|
||||
from compound import CompoundValidator, from_python
|
||||
|
||||
__all__ = ['ForEach']
|
||||
|
||||
|
||||
class ForEach(CompoundValidator):
|
||||
"""
|
||||
Use this to apply a validator/converter to each item in a list.
|
||||
|
||||
For instance::
|
||||
|
||||
ForEach(AsInt(), InList([1, 2, 3]))
|
||||
|
||||
Will take a list of values and try to convert each of them to
|
||||
an integer, and then check if each integer is 1, 2, or 3. Using
|
||||
multiple arguments is equivalent to::
|
||||
|
||||
ForEach(All(AsInt(), InList([1, 2, 3])))
|
||||
|
||||
Use convert_to_list=True if you want to force the input to be a
|
||||
list. This will turn non-lists into one-element lists, and None
|
||||
into the empty list. This tries to detect sequences by iterating
|
||||
over them (except strings, which aren't considered sequences).
|
||||
|
||||
ForEach will try to convert the entire list, even if errors are
|
||||
encountered. If errors are encountered, they will be collected
|
||||
and a single Invalid exception will be raised at the end (with
|
||||
error_list set).
|
||||
|
||||
If the incoming value is a set, then we return a set.
|
||||
"""
|
||||
|
||||
convert_to_list = True
|
||||
if_empty = NoDefault
|
||||
repeating = True
|
||||
_if_missing = ()
|
||||
|
||||
def attempt_convert(self, value, state, validate):
|
||||
if self.convert_to_list:
|
||||
value = self._convert_to_list(value)
|
||||
if self.if_empty is not NoDefault and not value:
|
||||
return self.if_empty
|
||||
if self.not_empty and not value:
|
||||
if validate is from_python and self.accept_python:
|
||||
return []
|
||||
raise Invalid(
|
||||
self.message('empty', state),
|
||||
value, state)
|
||||
new_list = []
|
||||
errors = []
|
||||
all_good = True
|
||||
is_set = isinstance(value, set)
|
||||
if state is not None:
|
||||
previous_index = getattr(state, 'index', NoDefault)
|
||||
previous_full_list = getattr(state, 'full_list', NoDefault)
|
||||
index = 0
|
||||
state.full_list = value
|
||||
try:
|
||||
for sub_value in value:
|
||||
if state:
|
||||
state.index = index
|
||||
index += 1
|
||||
good_pass = True
|
||||
for validator in self.validators:
|
||||
try:
|
||||
sub_value = validate(validator, sub_value, state)
|
||||
except Invalid, e:
|
||||
errors.append(e)
|
||||
all_good = False
|
||||
good_pass = False
|
||||
break
|
||||
if good_pass:
|
||||
errors.append(None)
|
||||
new_list.append(sub_value)
|
||||
if all_good:
|
||||
if is_set:
|
||||
new_list = set(new_list)
|
||||
return new_list
|
||||
else:
|
||||
raise Invalid(
|
||||
'Errors:\n%s' % '\n'.join([unicode(e) for e in errors if e]),
|
||||
value,
|
||||
state,
|
||||
error_list=errors)
|
||||
finally:
|
||||
if state is not None:
|
||||
if previous_index is NoDefault:
|
||||
try:
|
||||
del state.index
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
state.index = previous_index
|
||||
if previous_full_list is NoDefault:
|
||||
try:
|
||||
del state.full_list
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
state.full_list = previous_full_list
|
||||
|
||||
def empty_value(self, value):
|
||||
return []
|
||||
|
||||
class _IfMissing(object):
|
||||
def __get__(self, obj, type=None):
|
||||
if obj is None:
|
||||
return []
|
||||
elif obj._if_missing is ForEach._if_missing:
|
||||
return []
|
||||
else:
|
||||
return obj._if_missing
|
||||
def __set__(self, obj, value):
|
||||
obj._if_missing = value
|
||||
def __delete__(self, obj):
|
||||
obj._if_missing = NoDefault
|
||||
|
||||
if_missing = _IfMissing()
|
||||
del _IfMissing
|
||||
|
||||
def _convert_to_list(self, value):
|
||||
if isinstance(value, (str, unicode)):
|
||||
return [value]
|
||||
elif value is None:
|
||||
return []
|
||||
elif isinstance(value, (list, tuple)):
|
||||
return value
|
||||
try:
|
||||
for n in value:
|
||||
break
|
||||
return value
|
||||
## @@: Should this catch any other errors?:
|
||||
except TypeError:
|
||||
return [value]
|
||||
Reference in New Issue
Block a user