source: ralphm-patches/pubsub-subscription-options.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: 6.6 KB
  • wokkel/pubsub.py

    diff -r 3f7b69ddecb4 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'],
     
    419419        else:
    420420            raise BadRequest(text="Missing options form")
    421421
     422
     423    def _render_options(self, verbElement):
     424        verbElement.addChild(self.options.toElement())
     425
     426
     427    def _parse_optionsWithSubscribe(self, verbElement):
     428        for element in verbElement.parent.elements():
     429            if element.name == 'options' and element.uri == NS_PUBSUB:
     430                form = data_form.findForm(element,
     431                                          NS_PUBSUB_SUBSCRIBE_OPTIONS)
     432                if not form:
     433                    continue
     434
     435                self.options = form
     436                if form.formType != 'submit':
     437                    BadRequest(text="Unexpected form type %r" % form.formType)
     438
     439
     440    def _render_optionsWithSubscribe(self, verbElement):
     441        if self.options:
     442            optionsElement = verbElement.parent.addElement('options')
     443            self._render_options(optionsElement)
     444
     445
    422446    def parseElement(self, element):
    423447        """
    424448        Parse the publish-subscribe verb and parameters out of a request.
    425449        """
    426450        generic.Stanza.parseElement(self, element)
    427451
     452        verbs = []
     453        children = []
    428454        for child in element.pubsub.elements():
    429455            key = (self.stanzaType, child.uri, child.name)
    430456            try:
    431457                verb = self._requestVerbMap[key]
    432458            except KeyError:
    433459                continue
    434             else:
    435                 self.verb = verb
    436                 break
    437460
    438         if not self.verb:
     461            verbs.append(verb)
     462            children.append(child)
     463
     464        if not verbs:
    439465            raise NotImplementedError()
    440466
    441         for parameter in self._parameters[verb]:
     467        if len(verbs) > 1:
     468            if 'optionsSet' in verbs and 'subscribe' in verbs:
     469                self.verb = 'subscribe'
     470                child = children[verbs.index('subscribe')]
     471            else:
     472                raise NotImplementedError()
     473        else:
     474            self.verb = verbs[0]
     475
     476        for parameter in self._parameters[self.verb]:
    442477            getattr(self, '_parse_%s' % parameter)(child)
    443478
    444479
     480
    445481    def send(self, xs):
    446482        """
    447483        Send this request to its recipient.
     
    645681        return request.send(self.xmlstream)
    646682
    647683
    648     def subscribe(self, service, nodeIdentifier, subscriber, sender=None):
     684    def subscribe(self, service, nodeIdentifier, subscriber,
     685                        options=None, sender=None):
    649686        """
    650687        Subscribe to a publish subscribe node.
    651688
     
    656693        @param subscriber: The entity to subscribe to the node. This entity
    657694                           will get notifications of new published items.
    658695        @type subscriber: L{JID}
     696        @param options: Subscription options.
     697        @type options: C{dict}.
    659698        """
    660699        request = PubSubRequest('subscribe')
    661700        request.recipient = service
     
    663702        request.subscriber = subscriber
    664703        request.sender = sender
    665704
     705        if options:
     706            form = data_form.Form(formType='result',
     707                                  formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS)
     708            form.makeFields(options)
     709            request.options = form
     710
    666711        def cb(iq):
    667712            subscription = iq.pubsub.subscription["subscription"]
    668713
  • wokkel/test/test_pubsub.py

    diff -r 3f7b69ddecb4 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.
     
    718749        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
    719750        self.assertEqual('jid-required', err.appCondition.name)
    720751
     752
     753    def test_fromElementSubscribeWithOptions(self):
     754        """
     755        Test parsing a subscription request.
     756        """
     757
     758        xml = """
     759        <iq type='set' to='pubsub.example.org'
     760                       from='user@example.org'>
     761          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     762            <subscribe node='test' jid='user@example.org/Home'/>
     763            <options>
     764              <x xmlns="jabber:x:data" type='submit'>
     765                <field var='FORM_TYPE' type='hidden'>
     766                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
     767                </field>
     768                <field var='pubsub#deliver' type='boolean'
     769                       label='Enable delivery?'>
     770                  <value>1</value>
     771                </field>
     772              </x>
     773            </options>
     774          </pubsub>
     775        </iq>
     776        """
     777
     778        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     779        self.assertEqual('subscribe', request.verb)
     780        request.options.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
     781        self.assertEqual({'pubsub#deliver': True}, request.options.getValues())
     782
     783
    721784    def test_fromElementUnsubscribe(self):
    722785        """
    723786        Test parsing an unsubscription request.
Note: See TracBrowser for help on using the repository browser.