Changeset 29:dd4e908b9d12


Ignore:
Timestamp:
Aug 4, 2008, 8:55:45 AM (13 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@59
Message:

Implement type checking in data forms and incoming pubsub node config.

Author: ralphm.
Fixes #15.

Location:
wokkel
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • wokkel/data_form.py

    r25 r29  
    204204
    205205
    206     def toElement(self):
    207         """
    208         Return the DOM representation of this Field.
    209 
    210         @rtype L{domish.Element}.
     206    def typeCheck(self):
     207        """
     208        Check field properties agains the set field type.
    211209        """
    212210        if self.var is None and self.fieldType != 'fixed':
    213211            raise FieldNameRequiredError()
    214 
    215         field = domish.Element((NS_X_DATA, 'field'))
    216         field['type'] = self.fieldType
    217 
    218         if self.var is not None:
    219             field['var'] = self.var
    220212
    221213        if self.values:
     
    225217                raise TooManyValuesError()
    226218
     219            newValues = []
    227220            for value in self.values:
    228221                if self.fieldType == 'boolean':
    229222                    # We send out the textual representation of boolean values
    230                     value = unicode(bool(value)).lower()
     223                    value = bool(int(value))
    231224                elif self.fieldType in ('jid-single', 'jid-multi'):
    232225                    value = value.full()
    233226
    234                 field.addElement('value', content=value)
     227                newValues.append(value)
     228
     229            self.values = newValues
     230
     231    def toElement(self):
     232        """
     233        Return the DOM representation of this Field.
     234
     235        @rtype L{domish.Element}.
     236        """
     237
     238        self.typeCheck()
     239
     240        field = domish.Element((NS_X_DATA, 'field'))
     241        field['type'] = self.fieldType
     242
     243        if self.var is not None:
     244            field['var'] = self.var
     245
     246        for value in self.values:
     247            if self.fieldType == 'boolean':
     248                value = unicode(value).lower()
     249            field.addElement('value', content=value)
    235250
    236251        if self.fieldType in ('list-single', 'list-multi'):
     
    302317    @staticmethod
    303318    def fromDict(dictionary):
     319        kwargs = dictionary.copy()
     320
    304321        if 'type' in dictionary:
    305             dictionary['fieldType'] = dictionary['type']
    306             del dictionary['type']
     322            kwargs['fieldType'] = dictionary['type']
     323            del kwargs['type']
     324
    307325        if 'options' in dictionary:
    308326            options = []
    309327            for value, label in dictionary['options'].iteritems():
    310328                options.append(Option(value, label))
    311             dictionary['options'] = options
    312         return Field(**dictionary)
     329            kwargs['options'] = options
     330
     331        return Field(**kwargs)
    313332
    314333
     
    335354                         C{'FORM_TYPE'}, if set.
    336355    @type formNamespace: C{str}.
     356    @ivar fields: Dictionary of fields that have a name. Note that this is
     357                  meant to be used for reading, only. One should use
     358                  L{addField} for adding fields.
     359    @type fields: C{dict}
    337360    """
    338361
     
    343366        self.instructions = instructions or []
    344367        self.formNamespace = formNamespace
    345         self.fields = fields or []
    346 
     368
     369        self.fieldList = []
     370        self.fields = {}
     371
     372        if fields:
     373            for field in fields:
     374                self.addField(field)
    347375
    348376    def __repr__(self):
     
    360388        if self.fields:
    361389            r.append(", fields=")
    362             r.append(repr(self.fields))
     390            r.append(repr(self.fieldList))
    363391        r.append(")")
    364392        return u"".join(r)
     393
     394
     395    def addField(self, field):
     396        """
     397        Add a field to this form.
     398
     399        Fields are added in order, and L{fields} is a dictionary of the
     400        named fields, that is kept in sync only if this method is used for
     401        adding new fields. Multiple fields with the same name are disallowed.
     402        """
     403        if field.var is not None:
     404            if field.var in self.fields:
     405                raise Error("Duplicate field %r" % field.var)
     406
     407            self.fields[field.var] = field
     408
     409        self.fieldList.append(field)
    365410
    366411
     
    379424            form.addChild(field.toElement())
    380425
    381         for field in self.fields:
     426        for field in self.fieldList:
    382427            form.addChild(field.toElement())
    383428
     
    407452            form.formNamespace = field.value
    408453        else:
    409             form.fields.append(field)
     454            form.addField(field)
    410455
    411456    @staticmethod
     
    429474        values = {}
    430475
    431         for field in self.fields:
     476        for name, field in self.fields.iteritems():
    432477            if len(field.values) > 1:
    433478                value = field.values
     
    435480                value = field.value
    436481
    437             if field.var:
    438                 values[field.var] = value
     482            values[name] = value
    439483
    440484        return values
  • wokkel/pubsub.py

    r27 r29  
    527527                form = data_form.Form(formType="result",
    528528                                      formNamespace=NS_PUBSUB_META_DATA)
    529                 form.fields.append(
     529                form.addField(
    530530                        data_form.Field(
    531531                            var='pubsub#node_type',
     
    536536
    537537                for metaDatum in metaData:
    538                     form.fields.append(data_form.Field.fromDict(metaDatum))
     538                    form.addField(data_form.Field.fromDict(metaDatum))
    539539
    540540                info.append(form.toElement())
     
    693693
    694694
     695    def _makeFields(self, options, values):
     696        fields = []
     697        for name, value in values.iteritems():
     698            if name not in options:
     699                continue
     700
     701            option = {'var': name}
     702            option.update(options[name])
     703            if isinstance(value, list):
     704                option['values'] = value
     705            else:
     706                option['value'] = value
     707            fields.append(data_form.Field.fromDict(option))
     708        return fields
     709
    695710    def _formFromConfiguration(self, values):
    696711        options = self.getConfigurationOptions()
     712        fields = self._makeFields(options, values)
    697713        form = data_form.Form(formType="form",
    698                               formNamespace=NS_PUBSUB_NODE_CONFIG)
    699 
    700         for name, value in values.iteritems():
    701             if name in options:
    702                 option = {'var': name}
    703                 option.update(options[name])
    704                 if isinstance(value, list):
    705                     option['values'] = value
    706                 else:
    707                     option['value'] = value
    708                 form.fields.append(data_form.Field.fromDict(option))
     714                              formNamespace=NS_PUBSUB_NODE_CONFIG,
     715                              fields=fields)
    709716
    710717        return form
     718
     719    def _checkConfiguration(self, values):
     720        options = self.getConfigurationOptions()
     721        processedValues = {}
     722
     723        for key, value in values.iteritems():
     724            if key not in options:
     725                continue
     726
     727            option = {'var': key}
     728            option.update(options[key])
     729            field = data_form.Field.fromDict(option)
     730            if isinstance(value, list):
     731                field.values = value
     732            else:
     733                field.value = value
     734            field.typeCheck()
     735
     736            if isinstance(value, list):
     737                processedValues[key] = field.values
     738            else:
     739                processedValues[key] = field.value
     740
     741        return processedValues
    711742
    712743
     
    757788        if form:
    758789            if form.formType == 'submit':
    759                 options = form.getValues()
     790                options = self._checkConfiguration(form.getValues())
    760791
    761792                return self.setConfiguration(requestor, service,
  • wokkel/test/test_data_form.py

    r26 r29  
    116116        self.assertEquals(None, form.title)
    117117        self.assertEquals([], form.instructions)
    118         self.assertEquals([], form.fields)
     118        self.assertEquals({}, form.fields)
    119119
    120120
     
    164164        form = Form.fromElement(element)
    165165
    166         self.assertEquals(1, len(form.fields))
     166        self.assertEquals(1, len(form.fieldList))
     167        self.assertNotIn('field', form.fields)
    167168
    168169
     
    173174        form = Form.fromElement(element)
    174175
    175         self.assertEquals(2, len(form.fields))
    176         self.assertEquals('field1', form.fields[0].var)
    177         self.assertEquals('field2', form.fields[1].var)
     176        self.assertEquals(2, len(form.fieldList))
     177        self.assertIn('field1', form.fields)
     178        self.assertEquals('field1', form.fieldList[0].var)
     179        self.assertIn('field2', form.fields)
     180        self.assertEquals('field2', form.fieldList[1].var)
  • wokkel/test/test_pubsub.py

    r27 r29  
    632632            form = data_form.Form.fromElement(element.configure.x)
    633633            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
    634             fields = dict([(field.var, field) for field in form.fields])
     634            fields = form.fields
    635635
    636636            self.assertIn('pubsub#deliver_payloads', fields)
    637637            field = fields['pubsub#deliver_payloads']
    638638            self.assertEqual('boolean', field.fieldType)
    639             self.assertEqual(True, field.value)
     639            self.assertEqual(False, field.value)
    640640
    641641            self.assertIn('pubsub#persist_items', fields)
     
    674674        """
    675675
     676        def getConfigurationOptions():
     677            return {
     678                "pubsub#persist_items":
     679                    {"type": "boolean",
     680                     "label": "Persist items to storage"},
     681                "pubsub#deliver_payloads":
     682                    {"type": "boolean",
     683                     "label": "Deliver payloads with event notifications"}
     684                }
     685
    676686        def setConfiguration(requestor, service, nodeIdentifier, options):
    677687            self.assertEqual(JID('user@example.org'), requestor)
    678688            self.assertEqual(JID('pubsub.example.org'), service)
    679689            self.assertEqual('test', nodeIdentifier)
    680             self.assertEqual({'pubsub#deliver_payloads': '0',
    681                               'pubsub#persist_items': '1'}, options)
     690            self.assertEqual({'pubsub#deliver_payloads': False,
     691                              'pubsub#persist_items': True}, options)
    682692            return defer.succeed(None)
    683693
     694        self.service.getConfigurationOptions = getConfigurationOptions
    684695        self.service.setConfiguration = setConfiguration
    685696        return self.handleRequest(xml)
     
    714725
    715726
     727    def test_onConfigureSetIgnoreUnknown(self):
     728        """
     729        On a node configuration set request unknown fields should be ignored.
     730        """
     731
     732        xml = """
     733        <iq type='set' to='pubsub.example.org'
     734                       from='user@example.org'>
     735          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     736            <configure node='test'>
     737              <x xmlns='jabber:x:data' type='submit'>
     738                <field var='FORM_TYPE' type='hidden'>
     739                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     740                </field>
     741                <field var='pubsub#deliver_payloads'><value>0</value></field>
     742                <field var='x-myfield'><value>1</value></field>
     743              </x>
     744            </configure>
     745          </pubsub>
     746        </iq>
     747        """
     748
     749        def getConfigurationOptions():
     750            return {
     751                "pubsub#persist_items":
     752                    {"type": "boolean",
     753                     "label": "Persist items to storage"},
     754                "pubsub#deliver_payloads":
     755                    {"type": "boolean",
     756                     "label": "Deliver payloads with event notifications"}
     757                }
     758
     759        def setConfiguration(requestor, service, nodeIdentifier, options):
     760            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
     761
     762        self.service.getConfigurationOptions = getConfigurationOptions
     763        self.service.setConfiguration = setConfiguration
     764        return self.handleRequest(xml)
     765
     766
    716767    def test_onItems(self):
    717768        """
Note: See TracChangeset for help on using the changeset viewer.