source: ralphm-patches/pubsub-subscription-options.patch @ 17:0b77281b458c

Last change on this file since 17:0b77281b458c was 17:0b77281b458c, checked in by Ralph Meijer <ralphm@…>, 11 years ago

More consistent naming.

File size: 9.9 KB
  • wokkel/data_form.py

    diff -r 2919e60d3588 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,
     
    256257            elif self.fieldType in ('jid-single', 'jid-multi'):
    257258                value = value.full()
    258259
    259             field.addElement('value', content=value)
     260            field.addElement('value', content=unicode(value))
    260261
    261262        if asForm:
    262263            if self.fieldType in ('list-single', 'list-multi'):
     
    322323
    323324
    324325    @staticmethod
    325     def fromDict(dictionary):
    326         kwargs = dictionary.copy()
     326    def fromDict(fieldDict):
     327        kwargs = fieldDict.copy()
    327328
    328         if 'type' in dictionary:
    329             kwargs['fieldType'] = dictionary['type']
     329        if 'type' in fieldDict:
     330            kwargs['fieldType'] = fieldDict['type']
    330331            del kwargs['type']
    331332
    332         if 'options' in dictionary:
     333        if 'options' in fieldDict:
    333334            options = []
    334             for value, label in dictionary['options'].iteritems():
     335            for value, label in fieldDict['options'].iteritems():
    335336                options.append(Option(value, label))
    336337            kwargs['options'] = options
    337338
     
    416417        self.fieldList.append(field)
    417418
    418419
     420    def makeFields(self, values, fieldDefs=None, filterUnknown=True):
     421        """
     422        Create fields from values and add them to this form.
     423
     424        This creates fields from a mapping of name to value(s) and adds them to
     425        this form. If C{fieldDefs} is not C{None}, this is used to fill in
     426        additional properties of fields, like the field types, labels and
     427        possible options. If C{filterUnknown} is C{True} and C{fieldDefs} is
     428        not C{None}, fields will only be created from C{values} with a
     429        corresponding entry in C{fieldDefs}.
     430        """
     431        for name, value in values.iteritems():
     432            fieldDict = {'var': name}
     433
     434            if fieldDefs is not None:
     435                if name in fieldDefs:
     436                    fieldDict.update(fieldDefs[name])
     437                elif filterUnknown:
     438                    continue
     439
     440            if isinstance(value, list):
     441                fieldDict['values'] = value
     442                if 'type' not in fieldDict:
     443                    if value and hasattr(value[0], 'full'):
     444                        fieldDict['type'] = 'jid-multi'
     445                    else:
     446                        fieldDict['type'] = 'text-multi'
     447            else:
     448                fieldDict['value'] = value
     449                if 'type' not in fieldDict:
     450                    if hasattr(value, 'full'):
     451                        fieldDict['type'] = 'jid-single'
     452                    elif isinstance(value, bool):
     453                        fieldDict['type'] = 'boolean'
     454
     455            self.addField(Field.fromDict(fieldDict))
     456
     457
    419458    def toElement(self):
    420459        form = domish.Element((NS_X_DATA, 'x'))
    421460        form['type'] = self.formType
     
    489528            values[name] = value
    490529
    491530        return values
     531
     532
     533    def typeCheck(self, fieldDefs=None):
     534        for name, field in self.fields.iteritems():
     535            if fieldDefs and name in fieldDefs:
     536                field.fieldType = fieldDefs[name]['type']
     537
     538            field.typeCheck()
  • wokkel/pubsub.py

    diff -r 2919e60d3588 wokkel/pubsub.py
    a b  
    228228    # Map request verb to parameter handler names
    229229    _parameters = {
    230230        'publish': ['node', 'items'],
    231         'subscribe': ['nodeOrEmpty', 'jid'],
     231        'subscribe': ['nodeOrEmpty', 'jid', 'optionsWithSubscribe'],
    232232        'unsubscribe': ['nodeOrEmpty', 'jid'],
    233233        'optionsGet': ['nodeOrEmpty', 'jid'],
    234234        'optionsSet': ['nodeOrEmpty', 'jid', 'options'],
     
    445445                self.options = {}
    446446            else:
    447447                raise BadRequest(text="Unexpected form type %r" % form.formType)
    448         else:
     448        elif self.verb == 'optionsSet':
    449449            raise BadRequest(text="Missing options form")
    450450
     451
     452    def _parse_optionsWithSubscribe(self, verbElement):
     453        # _parse_options will be called with the options element.
     454        # No special processing is required here.
     455        pass
     456
     457
     458    def _render_options(self, verbElement):
     459        form = data_form.Form(formType='submit',
     460                              formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS)
     461        form.makeFields(values=self.options)
     462        verbElement.addChild(form.toElement())
     463
     464
     465    def _render_optionsWithSubscribe(self, verbElement):
     466        if self.options:
     467            optionsElement = verbElement.parent.addElement('options')
     468            self._render_options(optionsElement)
     469
     470
    451471    def parseElement(self, element):
    452472        """
    453473        Parse the publish-subscribe verb and parameters out of a request.
    454474        """
    455475        generic.Stanza.parseElement(self, element)
    456476
     477        verbs = []
     478        children = []
    457479        for child in element.pubsub.elements():
    458480            key = (self.stanzaType, child.uri, child.name)
    459481            try:
    460482                verb = self._requestVerbMap[key]
    461483            except KeyError:
    462484                continue
    463             else:
    464                 self.verb = verb
    465                 break
    466485
    467         if not self.verb:
     486            verbs.append(verb)
     487            children.append(child)
     488
     489        if not verbs:
    468490            raise NotImplementedError()
    469491
    470         for parameter in self._parameters[verb]:
    471             getattr(self, '_parse_%s' % parameter)(child)
     492        if len(verbs) > 1:
     493            if 'optionsSet' in verbs and 'subscribe' in verbs:
     494                self.verb = 'subscribe'
     495            else:
     496                raise NotImplementedError()
     497        else:
     498            self.verb = verbs[0]
     499
     500        for verb, child in zip(verbs, children):
     501            for parameter in self._parameters[verb]:
     502                getattr(self, '_parse_%s' % parameter)(child)
     503
    472504
    473505
    474506    def send(self, xs):
     
    674706        return request.send(self.xmlstream)
    675707
    676708
    677     def subscribe(self, service, nodeIdentifier, subscriber, sender=None):
     709    def subscribe(self, service, nodeIdentifier, subscriber,
     710                        options=None, sender=None):
    678711        """
    679712        Subscribe to a publish subscribe node.
    680713
     
    685718        @param subscriber: The entity to subscribe to the node. This entity
    686719                           will get notifications of new published items.
    687720        @type subscriber: L{JID}
     721        @param options: Subscription options.
     722        @type options: C{dict}.
    688723        """
    689724        request = PubSubRequest('subscribe')
    690725        request.recipient = service
    691726        request.nodeIdentifier = nodeIdentifier
    692727        request.subscriber = subscriber
     728        request.options = options
    693729        request.sender = sender
    694730
    695731        def cb(iq):
     
    10121048            return None
    10131049
    10141050
    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 
    10311051    def _formFromConfiguration(self, resource, values):
    1032         options = resource.getConfigurationOptions()
    1033         fields = self._makeFields(options, values)
     1052        fieldDefs = resource.getConfigurationOptions()
    10341053        form = data_form.Form(formType="form",
    1035                               formNamespace=NS_PUBSUB_NODE_CONFIG,
    1036                               fields=fields)
    1037 
     1054                              formNamespace=NS_PUBSUB_NODE_CONFIG)
     1055        form.makeFields(values, fieldDefs)
    10381056        return form
    10391057
    10401058
  • wokkel/test/test_pubsub.py

    diff -r 2919e60d3588 wokkel/test/test_pubsub.py
    a b  
    447447        return d
    448448
    449449
     450    def test_subscribeWithOptions(self):
     451        options = {'pubsub#deliver': False}
     452
     453        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
     454                                    JID('user@example.org'),
     455                                    options=options)
     456        iq = self.stub.output[-1]
     457
     458        # Check options present
     459        childNames = []
     460        for element in iq.pubsub.elements():
     461            if element.uri == NS_PUBSUB:
     462                childNames.append(element.name)
     463
     464        self.assertEqual(['subscribe', 'options'], childNames)
     465        form = data_form.Form.fromElement(iq.pubsub.options.x)
     466        form.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
     467        self.assertEqual(options, form.getValues())
     468
     469        # Send response
     470        response = toResponse(iq, 'result')
     471        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
     472        subscription = pubsub.addElement('subscription')
     473        subscription['node'] = 'test'
     474        subscription['jid'] = 'user@example.org'
     475        subscription['subscription'] = 'subscribed'
     476        self.stub.send(response)
     477
     478        return d
     479
     480
    450481    def test_subscribeWithSender(self):
    451482        """
    452483        Test sending subscription request from a specific JID.
     
    18951926            return defer.succeed({'pubsub#deliver_payloads': '0',
    18961927                                  'pubsub#persist_items': '1',
    18971928                                  'pubsub#owner': JID('user@example.org'),
    1898                                   'x-myfield': ['a', 'b']})
     1929                                  'x-myfield': 'a'})
    18991930
    19001931        def cb(element):
    19011932            self.assertEqual('pubsub', element.name)
Note: See TracBrowser for help on using the repository browser.