Ignore:
Timestamp:
Jul 7, 2008, 4:29:02 PM (14 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@55
Message:

Refactor Data Forms.

Author: ralphm.
Fixes #13.

This refactoring provides an abstract representation of Forms, Fields and
Options and each of those can be parsed from or unparsed to XML. This change
also simplifies testing in test_pubsub, by allowing the 'received' requests
to be represented as an XML snippit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • wokkel/pubsub.py

    r24 r25  
    174174        self.command = self.pubsub.addElement(verb)
    175175
     176
    176177    def send(self, to):
    177178        """
     
    199200        self.xmlstream.addObserver('/message/event[@xmlns="%s"]' %
    200201                                   NS_PUBSUB_EVENT, self._onEvent)
     202
    201203
    202204    def _onEvent(self, message):
     
    271273        return request.send(service).addCallback(cb)
    272274
     275
    273276    def deleteNode(self, service, nodeIdentifier):
    274277        """
     
    283286        request.command['node'] = nodeIdentifier
    284287        return request.send(service)
     288
    285289
    286290    def subscribe(self, service, nodeIdentifier, subscriber):
     
    315319        return request.send(service).addCallback(cb)
    316320
     321
    317322    def unsubscribe(self, service, nodeIdentifier, subscriber):
    318323        """
     
    331336        return request.send(service)
    332337
     338
    333339    def publish(self, service, nodeIdentifier, items=None):
    334340        """
     
    349355
    350356        return request.send(service)
     357
    351358
    352359    def items(self, service, nodeIdentifier, maxItems=None):
     
    431438            }
    432439
     440
    433441    def __init__(self):
    434442        self.discoIdentity = {'category': 'pubsub',
     
    437445
    438446        self.pubSubFeatures = []
     447
    439448
    440449    def connectionMade(self):
     
    444453        self.xmlstream.addObserver(PUBSUB_OWNER_SET, self.handleRequest)
    445454
     455
    446456    def getDiscoInfo(self, requestor, target, nodeIdentifier):
    447457        info = []
     
    454464                         for feature in self.pubSubFeatures])
    455465
    456             return defer.succeed(info)
    457         else:
    458             def toInfo(nodeInfo):
    459                 if not nodeInfo:
    460                     return []
    461 
    462                 (nodeType, metaData) = nodeInfo['type'], nodeInfo['meta-data']
    463                 info.append(disco.DiscoIdentity('pubsub', nodeType))
    464                 if metaData:
    465                     form = data_form.Form(type="result",
    466                                           form_type=NS_PUBSUB_META_DATA)
    467                     form.add_field("text-single",
    468                                    "pubsub#node_type",
    469                                    "The type of node (collection or leaf)",
    470                                    nodeType)
    471 
    472                     for metaDatum in metaData:
    473                         form.add_field(**metaDatum)
    474 
    475                     info.append(form)
    476                 return info
    477 
    478             d = self.getNodeInfo(requestor, target, nodeIdentifier)
    479             d.addCallback(toInfo)
    480             return d
     466        def toInfo(nodeInfo):
     467            if not nodeInfo:
     468                return
     469
     470            (nodeType, metaData) = nodeInfo['type'], nodeInfo['meta-data']
     471            info.append(disco.DiscoIdentity('pubsub', nodeType))
     472            if metaData:
     473                form = data_form.Form(formType="result",
     474                                      formNamespace=NS_PUBSUB_META_DATA)
     475                form.fields.append(
     476                        data_form.Field(
     477                            var='pubsub#node_type',
     478                            value=nodeType,
     479                            label='The type of node (collection or leaf)'
     480                        )
     481                )
     482
     483                for metaDatum in metaData:
     484                    form.fields.append(data_form.Field.fromDict(metaDatum))
     485
     486                info.append(form.toElement())
     487
     488        d = self.getNodeInfo(requestor, target, nodeIdentifier or '')
     489        d.addCallback(toInfo)
     490        d.addBoth(lambda result: info)
     491        return d
     492
    481493
    482494    def getDiscoItems(self, requestor, target, nodeIdentifier):
     
    489501        return d
    490502
     503
     504    def _findForm(self, element, formNamespace):
     505        if not element:
     506            return None
     507
     508        form = None
     509        for child in element.elements():
     510            try:
     511                form = data_form.Form.fromElement(child)
     512            except data_form.Error:
     513                continue
     514
     515            if form.formNamespace != NS_PUBSUB_NODE_CONFIG:
     516                continue
     517
     518        return form
     519
     520
    491521    def _onPublish(self, iq):
    492522        requestor = jid.internJID(iq["from"]).userhostJID()
     
    504534
    505535        return self.publish(requestor, service, nodeIdentifier, items)
     536
    506537
    507538    def _onSubscribe(self, iq):
     
    528559        return d
    529560
     561
    530562    def _onUnsubscribe(self, iq):
    531563        requestor = jid.internJID(iq["from"]).userhostJID()
     
    540572        return self.unsubscribe(requestor, service, nodeIdentifier, subscriber)
    541573
     574
    542575    def _onOptionsGet(self, iq):
    543576        raise Unsupported('subscription-options-unavailable')
    544577
     578
    545579    def _onOptionsSet(self, iq):
    546580        raise Unsupported('subscription-options-unavailable')
     581
    547582
    548583    def _onSubscriptions(self, iq):
     
    564599        return d
    565600
     601
    566602    def _onAffiliations(self, iq):
    567603        requestor = jid.internJID(iq["from"]).userhostJID()
     
    582618        d.addCallback(toResponse)
    583619        return d
     620
    584621
    585622    def _onCreate(self, iq):
     
    601638        return d
    602639
    603     def _formFromConfiguration(self, options):
    604         form = data_form.Form(type="form", form_type=NS_PUBSUB_NODE_CONFIG)
    605 
    606         for option in options:
    607             form.add_field(**option)
     640
     641    def _formFromConfiguration(self, values):
     642        options = self.getConfigurationOptions()
     643        form = data_form.Form(formType="form",
     644                              formNamespace=NS_PUBSUB_NODE_CONFIG)
     645
     646        for name, value in values.iteritems():
     647            if name in options:
     648                option = {'var': name}
     649                option.update(options[name])
     650                if isinstance(value, list):
     651                    option['values'] = value
     652                else:
     653                    option['value'] = value
     654                form.fields.append(data_form.Field.fromDict(option))
    608655
    609656        return form
     657
    610658
    611659    def _onDefault(self, iq):
     
    616664            response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
    617665            default = response.addElement("default")
    618             default.addChild(self._formFromConfiguration(options))
     666            default.addChild(self._formFromConfiguration(options).toElement())
    619667            return response
    620668
     
    623671        return d
    624672
     673
    625674    def _onConfigureGet(self, iq):
    626675        requestor = jid.internJID(iq["from"]).userhostJID()
     
    631680            response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
    632681            configure = response.addElement("configure")
    633             configure.addChild(self._formFromConfiguration(options))
     682            configure.addChild(self._formFromConfiguration(options).toElement())
    634683
    635684            if nodeIdentifier:
     
    642691        return d
    643692
     693
    644694    def _onConfigureSet(self, iq):
    645695        requestor = jid.internJID(iq["from"]).userhostJID()
     
    647697        nodeIdentifier = iq.pubsub.configure["node"]
    648698
    649         def getFormOptions(form):
    650             options = {}
    651 
    652             for element in form.elements():
    653                 if element.name == 'field' and \
    654                    element.uri == data_form.NS_X_DATA:
    655                     try:
    656                         options[element["var"]] = str(element.value)
    657                     except (KeyError, AttributeError):
    658                         raise BadRequest
    659 
    660             return options
    661 
    662699        # Search configuration form with correct FORM_TYPE and process it
    663700
    664         for element in iq.pubsub.configure.elements():
    665             if element.name != 'x' or element.uri != data_form.NS_X_DATA:
    666                 continue
    667 
    668             type = element.getAttribute("type")
    669             if type == "cancel":
    670                 return None
    671             elif type != "submit":
    672                 continue
    673 
    674             options = getFormOptions(element)
    675 
    676             if options["FORM_TYPE"] == NS_PUBSUB + "#node_config":
    677                 del options["FORM_TYPE"]
     701        form = self._findForm(iq.pubsub.configure, NS_PUBSUB_NODE_CONFIG)
     702
     703        if form:
     704            if form.formType == 'submit':
     705                options = form.getValues()
     706
    678707                return self.setConfiguration(requestor, service,
    679708                                             nodeIdentifier, options)
    680 
    681         raise BadRequest
     709            elif form.formType == 'cancel':
     710                return None
     711
     712        raise BadRequest()
     713
    682714
    683715    def _onItems(self, iq):
     
    721753        return d
    722754
     755
    723756    def _onRetract(self, iq):
    724757        requestor = jid.internJID(iq["from"]).userhostJID()
     
    741774                            itemIdentifiers)
    742775
     776
    743777    def _onPurge(self, iq):
    744778        requestor = jid.internJID(iq["from"]).userhostJID()
     
    752786        return self.purge(requestor, service, nodeIdentifier)
    753787
     788
    754789    def _onDelete(self, iq):
    755790        requestor = jid.internJID(iq["from"]).userhostJID()
     
    763798        return self.delete(requestor, service, nodeIdentifier)
    764799
     800
    765801    def _onAffiliationsGet(self, iq):
    766802        raise Unsupported('modify-affiliations')
    767803
     804
    768805    def _onAffiliationsSet(self, iq):
    769806        raise Unsupported('modify-affiliations')
    770807
     808
    771809    def _onSubscriptionsGet(self, iq):
    772810        raise Unsupported('manage-subscriptions')
     811
    773812
    774813    def _onSubscriptionsSet(self, iq):
     
    788827            self.send(message)
    789828
     829
    790830    def notifyDelete(self, service, nodeIdentifier, recipients):
    791831        for recipient in recipients:
     
    798838            self.send(message)
    799839
     840
    800841    def getNodeInfo(self, requestor, service, nodeIdentifier):
    801842        return None
    802843
     844
    803845    def getNodes(self, requestor, service):
    804846        return []
    805847
     848
    806849    def publish(self, requestor, service, nodeIdentifier, items):
    807850        raise Unsupported('publish')
    808851
     852
    809853    def subscribe(self, requestor, service, nodeIdentifier, subscriber):
    810854        raise Unsupported('subscribe')
    811855
     856
    812857    def unsubscribe(self, requestor, service, nodeIdentifier, subscriber):
    813858        raise Unsupported('subscribe')
    814859
     860
    815861    def subscriptions(self, requestor, service):
    816862        raise Unsupported('retrieve-subscriptions')
    817863
     864
    818865    def affiliations(self, requestor, service):
    819866        raise Unsupported('retrieve-affiliations')
    820867
     868
    821869    def create(self, requestor, service, nodeIdentifier):
    822870        raise Unsupported('create-nodes')
    823871
     872
     873    def getConfigurationOptions(self):
     874        return {}
     875
     876
    824877    def getDefaultConfiguration(self, requestor, service):
    825878        raise Unsupported('retrieve-default')
    826879
     880
    827881    def getConfiguration(self, requestor, service, nodeIdentifier):
    828882        raise Unsupported('config-node')
    829883
     884
    830885    def setConfiguration(self, requestor, service, nodeIdentifier, options):
    831886        raise Unsupported('config-node')
     887
    832888
    833889    def items(self, requestor, service, nodeIdentifier, maxItems,
     
    835891        raise Unsupported('retrieve-items')
    836892
     893
    837894    def retract(self, requestor, service, nodeIdentifier, itemIdentifiers):
    838895        raise Unsupported('retract-items')
    839896
     897
    840898    def purge(self, requestor, service, nodeIdentifier):
    841899        raise Unsupported('purge-nodes')
    842900
     901
    843902    def delete(self, requestor, service, nodeIdentifier):
    844903        raise Unsupported('delete-nodes')
Note: See TracChangeset for help on using the changeset viewer.