source: ralphm-patches/pubsub-forms.patch @ 21:6e73325a5473

Last change on this file since 21:6e73325a5473 was 21:6e73325a5473, checked in by Ralph Meijer <ralphm@…>, 10 years ago

Split off data forms changes.

File size: 10.0 KB
  • wokkel/data_form.py

    diff -r 2ad7e6f72b63 -r 438b64816faa wokkel/data_form.py
    a b  
    7676            option['label'] = self.label
    7777        return option
    7878
     79
    7980    @staticmethod
    8081    def fromElement(element):
    8182        valueElements = list(domish.generateElementsQNamed(element.children,
     
    212213
    213214        if self.values:
    214215            if (self.fieldType not in ('hidden', 'jid-multi', 'list-multi',
    215                                  'text-multi') and
     216                                       'text-multi') and
    216217                len(self.values) > 1):
    217218                raise TooManyValuesError()
    218219
     
    233234
    234235            self.values = newValues
    235236
     237
    236238    def toElement(self, asForm=False):
    237239        """
    238240        Return the DOM representation of this Field.
     
    256258            elif self.fieldType in ('jid-single', 'jid-multi'):
    257259                value = value.full()
    258260
    259             field.addElement('value', content=value)
     261            field.addElement('value', content=unicode(value))
    260262
    261263        if asForm:
    262264            if self.fieldType in ('list-single', 'list-multi'):
     
    322324
    323325
    324326    @staticmethod
    325     def fromDict(dictionary):
    326         kwargs = dictionary.copy()
     327    def fromDict(fieldDict):
     328        kwargs = fieldDict.copy()
    327329
    328         if 'type' in dictionary:
    329             kwargs['fieldType'] = dictionary['type']
     330        if 'type' in fieldDict:
     331            kwargs['fieldType'] = fieldDict['type']
    330332            del kwargs['type']
    331333
    332         if 'options' in dictionary:
     334        if 'options' in fieldDict:
    333335            options = []
    334             for value, label in dictionary['options'].iteritems():
     336            for value, label in fieldDict['options'].iteritems():
    335337                options.append(Option(value, label))
    336338            kwargs['options'] = options
    337339
     
    343345    """
    344346    Data Form.
    345347
    346     There are two similarly named properties of forms. The L{formType} is the
     348    There are two similarly named properties of forms. The C{formType} is the
    347349    the so-called type of the form, and is set as the C{'type'} attribute
    348350    on the form's root element.
    349351
     
    351353    provide a context for the field names used in this form, by setting a
    352354    special hidden field named C{'FORM_TYPE'}, to put the names of all
    353355    other fields in the namespace of the value of that field. This namespace
    354     is recorded in the L{formNamespace} instance variable.
     356    is recorded in the C{formNamespace} instance variable.
    355357
    356358    @ivar formType: Type of form. One of C{'form'}, C{'submit'}, {'cancel'},
    357359                    or {'result'}.
    358     @type formType: C{str}.
     360    @type formType: C{str}
     361
    359362    @ivar formNamespace: The optional namespace of the field names for this
    360                          form. This goes in the special field named
    361                          C{'FORM_TYPE'}, if set.
    362     @type formNamespace: C{str}.
    363     @ivar fields: Dictionary of fields that have a name. Note that this is
    364                   meant to be used for reading, only. One should use
    365                   L{addField} for adding fields.
     363        form. This goes in the special field named C{'FORM_TYPE'}, if set.
     364    @type formNamespace: C{str}
     365
     366    @ivar fields: Dictionary of named fields. Note that this is meant to be
     367        used for reading, only. One should use L{addField} or L{makeFields} and
     368        L{removeField} for adding and removing fields.
    366369    @type fields: C{dict}
     370
     371    @ivar fieldList: List of all fields, in the order they are added. Like
     372        C{fields}, this is meant to be used for reading, only.
     373    @type fieldList: C{list}
     374
    367375    """
    368376
    369377    def __init__(self, formType, title=None, instructions=None,
     
    403411        """
    404412        Add a field to this form.
    405413
    406         Fields are added in order, and L{fields} is a dictionary of the
     414        Fields are added in order, and C{fields} is a dictionary of the
    407415        named fields, that is kept in sync only if this method is used for
    408416        adding new fields. Multiple fields with the same name are disallowed.
    409417        """
     
    416424        self.fieldList.append(field)
    417425
    418426
     427    def removeField(self, field):
     428        """
     429        Remove a field from this form.
     430        """
     431        self.fieldList.remove(field)
     432
     433        if field.var is not None:
     434            del self.fields[field.var]
     435
     436
     437    def makeFields(self, values, fieldDefs=None, filterUnknown=True):
     438        """
     439        Create fields from values and add them to this form.
     440
     441        This creates fields from a mapping of name to value(s) and adds them to
     442        this form. If C{fieldDefs} is not C{None}, this is used to fill in
     443        additional properties of fields, like the field types, labels and
     444        possible options. If C{filterUnknown} is C{True} and C{fieldDefs} is
     445        not C{None}, fields will only be created from C{values} with a
     446        corresponding entry in C{fieldDefs}.
     447
     448        @param values: Values to create fields from.
     449        @type values: C{dict}
     450
     451        @param fieldDefs: Field definitions as a dictionary. See
     452            L{wokkel.iwokkel.IPubSubService.getConfigurationOptions}
     453        @type fieldDefs: C{dict}
     454
     455        @param filterUnknown: If C{True}, ignore fields that are not in
     456            C{fieldDefs}.
     457        @type filterUnknown: C{bool}
     458        """
     459        for name, value in values.iteritems():
     460            fieldDict = {'var': name}
     461
     462            if fieldDefs is not None:
     463                if name in fieldDefs:
     464                    fieldDict.update(fieldDefs[name])
     465                elif filterUnknown:
     466                    continue
     467
     468            if isinstance(value, list):
     469                fieldDict['values'] = value
     470                if 'type' not in fieldDict:
     471                    if value and hasattr(value[0], 'full'):
     472                        fieldDict['type'] = 'jid-multi'
     473                    else:
     474                        fieldDict['type'] = 'text-multi'
     475            else:
     476                fieldDict['value'] = value
     477                if 'type' not in fieldDict:
     478                    if hasattr(value, 'full'):
     479                        fieldDict['type'] = 'jid-single'
     480                    elif isinstance(value, bool):
     481                        fieldDict['type'] = 'boolean'
     482
     483            self.addField(Field.fromDict(fieldDict))
     484
     485
    419486    def toElement(self):
     487        """
     488        Return the DOM representation of this Form.
     489
     490        @rtype: L{domish.Element}
     491        """
    420492        form = domish.Element((NS_X_DATA, 'x'))
    421493        form['type'] = self.formType
    422494
     
    477549
    478550        return form
    479551
     552
    480553    def getValues(self):
     554        """
     555        Extract values from the named form fields.
     556
     557        For all named fields, the corresponding value or values are
     558        returned in a dictionary keyed by the field name. For multi-value
     559        fields, the dictionary value is a list, otherwise a single value.
     560
     561        @rtype: C{dict}
     562        """
    481563        values = {}
    482564
    483565        for name, field in self.fields.iteritems():
     
    489571            values[name] = value
    490572
    491573        return values
     574
     575
     576    def typeCheck(self, fieldDefs, filterUnknown=False):
     577        """
     578        Check values of fields according to the field definition.
     579
     580        This method walks all named fields to check their values against their
     581        type. The field definition in C{fieldDefs} is used to check the field
     582        type. Unknown fields are ignored.
     583
     584        If the field type is C{None} (when not set by the receiving entity),
     585        C{'text-single'} is assumed, as this is the default value.
     586
     587        @param fieldDefs: Field definitions as a dictionary. See
     588            L{wokkel.iwokkel.IPubSubService.getConfigurationOptions}
     589        @type fieldDefs: C{dict}
     590
     591        @param filterUnknown: If C{True}, remove fields that are not in
     592            C{fieldDefs}.
     593        @type filterUnknown: C{bool}
     594        """
     595
     596        filtered = []
     597
     598        for name, field in self.fields.iteritems():
     599            if name in fieldDefs:
     600                if field.fieldType is None:
     601                    field.fieldType = fieldDefs[name]['type']
     602                elif field.fieldType != fieldDefs[name]['type']:
     603                    raise TypeError("Field type for %r is %r, expected %r" %
     604                                    (name,
     605                                     field.fieldType,
     606                                     fieldDefs[name]['type']))
     607                else:
     608                    # Field type is correct
     609                    pass
     610                field.typeCheck()
     611            elif filterUnknown:
     612                filtered.append(field)
     613            else:
     614                # Unknown field, not filtering
     615                pass
     616
     617        for field in filtered:
     618            self.removeField(field)
  • wokkel/pubsub.py

    diff -r 2ad7e6f72b63 -r 438b64816faa wokkel/pubsub.py
    a b  
    10121012            return None
    10131013
    10141014
    1015     def _makeFields(self, options, values):
    1016         fields = []
    1017         for name, value in values.iteritems():
    1018             if name not in options:
    1019                 continue
    1020 
    1021             option = {'var': name}
    1022             option.update(options[name])
    1023             if isinstance(value, list):
    1024                 option['values'] = value
    1025             else:
    1026                 option['value'] = value
    1027             fields.append(data_form.Field.fromDict(option))
    1028         return fields
    1029 
    1030 
    10311015    def _formFromConfiguration(self, resource, values):
    1032         options = resource.getConfigurationOptions()
    1033         fields = self._makeFields(options, values)
     1016        fieldDefs = resource.getConfigurationOptions()
    10341017        form = data_form.Form(formType="form",
    1035                               formNamespace=NS_PUBSUB_NODE_CONFIG,
    1036                               fields=fields)
    1037 
     1018                              formNamespace=NS_PUBSUB_NODE_CONFIG)
     1019        form.makeFields(values, fieldDefs)
    10381020        return form
    10391021
    10401022
Note: See TracBrowser for help on using the repository browser.