Changeset 304

Show
Ignore:
Timestamp:
04/03/08 17:04:10 (9 months ago)
Author:
matt
Message:

Enhance and fix the Sequence type. It's now possible to control the validation
and end result better. I also added an example of ways to use them.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r298 r304  
     12008-04-03  Matt Goodall <matt@pollenation.net> 
     2 
     3        Enhanced the Sequence type and the TextAreaList (the default widget for the 
     4        type). 
     5         
     6        The TextAreaList no longer strips all lines, leaving it to the Sequence's 
     7        item type to decide. 
     8 
     9        The Sequence now also runs it's type's validator on each item allowing 
     10        constructs such as: 
     11 
     12                Sequence(String(validators=[LengthValidator(min=2)]), 
     13                        validators=[LengthValidator(max=3, unit=u"lines")]) 
     14 
     15        i.e. a list containing a maximum of 3 strings, where each string is at 
     16        least 2 characters long. 
     17 
    1182007-09-29  Matt Goodall <matt@pollenation.net> 
    219 
  • trunk/formal/examples/main.py

    r289 r304  
    2727    'formal.examples.textareawithselect.TextAreaWithSelectFormPage', 
    2828    'formal.examples.richtextarea.RichTextAreaFormPage', 
     29    'formal.examples.sequences.SequencesFormPage', 
    2930    ] 
    3031 
  • trunk/formal/types.py

    r298 r304  
    134134 
    135135    def validate(self, value): 
    136         # Map empty sequence to None 
     136        # Map empty sequence to None. Otherwise validate each item according to 
     137        # type. 
    137138        if not value: 
    138             value = None 
    139         return super(Sequence, self).validate(value) 
     139            d = defer.succeed(None) 
     140        else: 
     141            d = self._validateItems(value) 
     142        # Return superclass's response 
     143        return d.addCallback(super(Sequence, self).validate) 
     144 
     145    def _validateItems(self, value): 
     146 
     147        def validated(response): 
     148            for (success, result) in response: 
     149                if not success: 
     150                    raise result 
     151                yield result 
     152 
     153        d = defer.DeferredList([self.type.validate(item) for item in value], 
     154                consumeErrors=True) 
     155        d.addCallback(validated) 
     156        d.addCallback(list) 
     157        return d 
    140158 
    141159 
  • trunk/formal/validation.py

    r301 r304  
    6363    implements(iformal.IValidator) 
    6464     
    65     def __init__(self, min=None, max=None): 
     65    def __init__(self, min=None, max=None, unit="characters"): 
    6666        self.min = min 
    6767        self.max = max 
     68        self.unit = unit 
    6869        assert self.min is not None or self.max is not None 
    6970         
    7071    def validationErrorMessage(self, field): 
    7172        if self.min is not None and self.max is None: 
    72             return 'Must be longer than %r characters'%(self.min,
     73            return 'Must be at least %r %s'%(self.min, self.unit
    7374        if self.min is None and self.max is not None: 
    74             return 'Must be shorter than %r characters'%(self.max,
    75         return 'Must be between %r and %r characters'%(self.min, self.max
     75            return 'Must be at most %r %s'%(self.max, self.unit
     76        return 'Must be between %r and %r %s'%(self.min, self.max, self.unit
    7677     
    7778    def validate(self, field, value): 
     
    9798    def validationErrorMessage(self, field): 
    9899        if self.min is not None and self.max is None: 
    99             return 'Must be greater than %r'%(self.min,) 
     100            return 'Must be %r or greater'%(self.min,) 
    100101        if self.min is None and self.max is not None: 
    101             return 'Must be less than %r'%(self.max,) 
     102            return 'Must be %r or less'%(self.max,) 
    102103        return 'Must be between %r and %r'%(self.min, self.max) 
    103104     
  • trunk/formal/widget.py

    r294 r304  
    194194        # Get the whole string 
    195195        value = args.get(key, [''])[0].decode(util.getPOSTCharset(ctx)) 
    196         # Split into lines 
    197         values = value.splitlines() 
    198         # Strip each line 
    199         values = [v.strip() for v in values] 
    200         # Discard empty lines 
    201         values = [v for v in values if v] 
     196        # Split into lines, discarding empty lines 
     197        values = [line for line in value.splitlines() if line.strip()] 
    202198        # Convert values to correct type 
    203199        converter = iformal.IStringConvertible(self.original.type)