Changeset 307

Show
Ignore:
Timestamp:
06/24/08 15:06:38 (7 months ago)
Author:
matt
Message:

Added a Tuple type.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r304 r307  
     12008-06-24  Matt Goodall <matt@pollenation.net> 
     2 
     3        Added a Tuple type. It allows the entry of multiple values using a text 
     4        field, splitting the text field and ensuring the tuple items are the 
     5        correct type. 
     6 
    172008-04-03  Matt Goodall <matt@pollenation.net> 
    28 
  • trunk/formal/__init__.py

    r289 r307  
    4242registerAdapter(TextInput, Integer, iformal.IWidget) 
    4343registerAdapter(TextInput, Float, iformal.IWidget) 
     44registerAdapter(TextInput, Tuple, iformal.IWidget) 
    4445registerAdapter(Checkbox, Boolean, iformal.IWidget) 
    4546registerAdapter(DatePartsInput, Date, iformal.IWidget) 
     
    6061registerAdapter(converters.NullConverter, Sequence, iformal.ISequenceConvertible) 
    6162registerAdapter(converters.SequenceToStringConverter, Sequence, iformal.IStringConvertible) 
     63registerAdapter(converters.TupleToStringConverter, Tuple, iformal.IStringConvertible) 
     64 
    6265try: 
    6366    Decimal 
  • trunk/formal/converters.py

    r256 r307  
    33""" 
    44 
     5from StringIO import StringIO 
     6import csv 
    57from datetime import date, time 
    68try: 
     
    178180 
    179181 
     182class TupleToStringConverter(object): 
     183 
     184    def __init__(self, type): 
     185        self.type = type 
     186 
     187    def fromType(self, value): 
     188        if value is None: 
     189            return "" 
     190        row = [iformal.IStringConvertible(t).fromType(v) for (t,v) in 
     191                zip(self.type.fields, value)] 
     192        row = [(i or "").encode("utf-8") for i in row] 
     193        out = StringIO() 
     194        csv.writer(out, delimiter=self.type.delimiter).writerow(row) 
     195        return out.getvalue().decode("utf-8") 
     196 
     197    def toType(self, value): 
     198        if value is not None: 
     199            value = value.strip() 
     200        if not value: 
     201            return None 
     202        value = value.encode("utf-8") 
     203        row = csv.reader(StringIO(value), delimiter=self.type.delimiter).next() 
     204        row = [i.strip() for i in row] 
     205        row = [i.decode("utf-8") for i in row] 
     206        if len(row) != len(self.type.fields): 
     207            raise validation.FieldValidationError("Please enter %d values, separated by a %s" % (len(self.type.fields), self.type.delimiter)) 
     208        value = [iformal.IStringConvertible(t).toType(v) for (t,v) in 
     209                zip(self.type.fields, row)] 
     210        return tuple(value) 
     211 
     212 
     213 
    180214class SequenceToStringConverter(_Adapter): 
    181215    implements( iformal.IStringConvertible) 
  • trunk/formal/types.py

    r304 r307  
    99    haveDecimal = False 
    1010from zope.interface import implements 
    11 from twisted.internet import defer 
     11from twisted.internet import defer, task 
    1212 
    1313from formal import iformal, validation 
     
    123123 
    124124 
     125class Tuple(Type): 
     126 
     127    delimeter = "," 
     128    fields = None 
     129 
     130    def __init__(self, **k): 
     131        fields = k.pop("fields", None) 
     132        delimiter = k.pop("delimiter", None) 
     133        super(Tuple, self).__init__(**k) 
     134        if fields is not None: 
     135            self.fields = fields 
     136        if delimiter is not None: 
     137            self.delimiter = delimiter 
     138 
     139    def validate(self, value): 
     140        if not value: 
     141            return super(Tuple, self).validate(None) 
     142        def driver(): 
     143            for (f,v) in zip(self.fields, value): 
     144                yield defer.maybeDeferred(f.validate, v).addCallback(result.append) 
     145        # Map the items to their validated versions. 
     146        result = [] 
     147        d = task.coiterate(driver()) 
     148        # Call the super class with the result. 
     149        d.addCallback(lambda ignore: super(Tuple, self).validate(tuple(result))) 
     150        return d 
     151 
     152 
    125153class Sequence(Type): 
    126154 
     
    200228 
    201229__all__ = [ 
    202     'Boolean', 'Date', 'File', 'Float', 'Integer', 'Sequence', 'String', 'Time', 'RichTextType', 'RichText', 
     230    'Boolean', 'Date', 'File', 'Float', 'Integer', 'Sequence', 'String', 
     231    'Time', 'Tuple', 'RichTextType', 'RichText', 
    203232    ] 
    204233 
  • trunk/setup.py

    r306 r307  
    33setup( 
    44    name='formal', 
    5     version='0.18', 
     5    version='0.19', 
    66    description='HTML forms framework for Nevow', 
    77    author='Matt Goodall',