Changeset 18:4812cc70807d


Ignore:
Timestamp:
Apr 16, 2008, 4:08:15 PM (12 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@48
Message:

Add maxItems argument to PubSubClient?.items(), lot of docs and tests.

Location:
wokkel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • wokkel/pubsub.py

    r17 r18  
    7878
    7979
     80
    8081class SubscriptionPending(Exception):
    8182    """
    8283    Raised when the requested subscription is pending acceptance.
    8384    """
     85
    8486
    8587
     
    8991    becoming active.
    9092    """
     93
    9194
    9295
     
    104107
    105108
     109
    106110class Unsupported(PubSubError):
    107111    def __init__(self, feature, text=None):
     
    112116
    113117
     118
    114119class OptionsUnavailable(Unsupported):
    115120    def __init__(self):
    116121        Unsupported.__init__(self, 'subscription-options-unavailable')
     122
    117123
    118124
     
    136142        """
    137143
    138         domish.Element.__init__(self, (None, 'item'))
     144        domish.Element.__init__(self, (NS_PUBSUB, 'item'))
    139145        if id is not None:
    140146            self['id'] = id
     
    146152
    147153
    148 class PubSubRequest(xmlstream.IQ):
    149     """
    150     Base class for publish subscribe user requests.
    151 
    152     @cvar namespace: request namespace
    153     @cvar verb: request verb
    154     @cvar method: type attribute of the IQ request. Either C{'set'} or C{'get'}
    155     @ivar command: command element of the request. This is the direct child of
     154
     155class _PubSubRequest(xmlstream.IQ):
     156    """
     157    Publish subscribe request.
     158
     159    @ivar verb: Request verb
     160    @type verb: C{str}
     161    @ivar namespace: Request namespace.
     162    @type namespace: C{str}
     163    @ivar method: Type attribute of the IQ request. Either C{'set'} or C{'get'}
     164    @type method: C{str}
     165    @ivar command: Command element of the request. This is the direct child of
    156166                   the C{pubsub} element in the C{namespace} with the name
    157167                   C{verb}.
    158168    """
    159169
    160     namespace = NS_PUBSUB
    161     method = 'set'
    162 
    163     def __init__(self, xs):
    164         xmlstream.IQ.__init__(self, xs, self.method)
    165         self.addElement((self.namespace, 'pubsub'))
    166 
    167         self.command = self.pubsub.addElement(self.verb)
     170    def __init__(self, xs, verb, namespace=NS_PUBSUB, method='set'):
     171        xmlstream.IQ.__init__(self, xs, method)
     172        self.addElement((namespace, 'pubsub'))
     173
     174        self.command = self.pubsub.addElement(verb)
    168175
    169176    def send(self, to):
     
    181188
    182189
    183 class CreateNode(PubSubRequest):
    184     verb = 'create'
    185 
    186     def __init__(self, xs, node=None):
    187         PubSubRequest.__init__(self, xs)
    188         if node:
    189             self.command["node"] = node
    190 
    191 
    192 class DeleteNode(PubSubRequest):
    193     verb = 'delete'
    194     def __init__(self, xs, node):
    195         PubSubRequest.__init__(self, xs)
    196         self.command["node"] = node
    197 
    198 
    199 class Subscribe(PubSubRequest):
    200     verb = 'subscribe'
    201 
    202     def __init__(self, xs, node, subscriber):
    203         PubSubRequest.__init__(self, xs)
    204         self.command["node"] = node
    205         self.command["jid"] = subscriber.full()
    206 
    207 
    208 class Unsubscribe(PubSubRequest):
    209     verb = 'unsubscribe'
    210 
    211     def __init__(self, xs, node, subscriber):
    212         PubSubRequest.__init__(self, xs)
    213         self.command["node"] = node
    214         self.command["jid"] = subscriber.full()
    215 
    216 
    217 class Publish(PubSubRequest):
    218     verb = 'publish'
    219 
    220     def __init__(self, xs, node):
    221         PubSubRequest.__init__(self, xs)
    222         self.command["node"] = node
    223 
    224     def addItem(self, id=None, payload=None):
    225         item = self.command.addElement("item")
    226         item.addChild(payload)
    227 
    228         if id is not None:
    229             item["id"] = id
    230 
    231         return item
    232 
    233 class Items(PubSubRequest):
    234     verb = 'items'
    235     method = 'get'
    236 
    237     def __init__(self, xs, node):
    238         PubSubRequest.__init__(self, xs)
    239         self.command["node"] = node
    240190
    241191class PubSubClient(XMPPHandler):
     
    297247
    298248    def createNode(self, service, nodeIdentifier=None):
    299         request = CreateNode(self.xmlstream, nodeIdentifier)
     249        """
     250        Create a publish subscribe node.
     251
     252        @param service: The publish subscribe service to create the node at.
     253        @type service: L{JID}
     254        @param nodeIdentifier: Optional suggestion for the id of the node.
     255        @type nodeIdentifier: C{unicode}
     256        """
     257
     258
     259        request = _PubSubRequest(self.xmlstream, 'create')
     260        if nodeIdentifier:
     261            request.command['node'] = nodeIdentifier
    300262
    301263        def cb(iq):
     
    310272
    311273    def deleteNode(self, service, nodeIdentifier):
    312         return DeleteNode(self.xmlstream, nodeIdentifier).send(service)
     274        """
     275        Delete a publish subscribe node.
     276
     277        @param service: The publish subscribe service to delete the node from.
     278        @type service: L{JID}
     279        @param nodeIdentifier: The identifier of the node.
     280        @type nodeIdentifier: C{unicode}
     281        """
     282        request = _PubSubRequest(self.xmlstream, 'delete')
     283        request.command['node'] = nodeIdentifier
     284        return request.send(service)
    313285
    314286    def subscribe(self, service, nodeIdentifier, subscriber):
    315         request = Subscribe(self.xmlstream, nodeIdentifier, subscriber)
     287        """
     288        Subscribe to a publish subscribe node.
     289
     290        @param service: The publish subscribe service that keeps the node.
     291        @type service: L{JID}
     292        @param nodeIdentifier: The identifier of the node.
     293        @type nodeIdentifier: C{unicode}
     294        @param subscriber: The entity to subscribe to the node. This entity
     295                           will get notifications of new published items.
     296        @type subscriber: L{JID}
     297        """
     298        request = _PubSubRequest(self.xmlstream, 'subscribe')
     299        request.command['node'] = nodeIdentifier
     300        request.command['jid'] = subscriber.full()
    316301
    317302        def cb(iq):
     
    331316
    332317    def unsubscribe(self, service, nodeIdentifier, subscriber):
    333         request = Unsubscribe(self.xmlstream, nodeIdentifier, subscriber)
     318        """
     319        Unsubscribe from a publish subscribe node.
     320
     321        @param service: The publish subscribe service that keeps the node.
     322        @type service: L{JID}
     323        @param nodeIdentifier: The identifier of the node.
     324        @type nodeIdentifier: C{unicode}
     325        @param subscriber: The entity to unsubscribe from the node.
     326        @type subscriber: L{JID}
     327        """
     328        request = _PubSubRequest(self.xmlstream, 'unsubscribe')
     329        request.command['node'] = nodeIdentifier
     330        request.command['jid'] = subscriber.full()
    334331        return request.send(service)
    335332
    336     def publish(self, service, nodeIdentifier, items=[]):
    337         request = Publish(self.xmlstream, nodeIdentifier)
    338         for item in items:
    339             request.command.addChild(item)
     333    def publish(self, service, nodeIdentifier, items=None):
     334        """
     335        Publish to a publish subscribe node.
     336
     337        @param service: The publish subscribe service that keeps the node.
     338        @type service: L{JID}
     339        @param nodeIdentifier: The identifier of the node.
     340        @type nodeIdentifier: C{unicode}
     341        @param items: Optional list of L{Item}s to publish.
     342        @type items: C{list}
     343        """
     344        request = _PubSubRequest(self.xmlstream, 'publish')
     345        request.command['node'] = nodeIdentifier
     346        if items:
     347            for item in items:
     348                request.command.addChild(item)
    340349
    341350        return request.send(service)
    342351
    343     def items(self, service, nodeIdentifier):
     352    def items(self, service, nodeIdentifier, maxItems=None):
     353        """
     354        Retrieve previously published items from a publish subscribe node.
     355
     356        @param service: The publish subscribe service that keeps the node.
     357        @type service: L{JID}
     358        @param nodeIdentifier: The identifier of the node.
     359        @type nodeIdentifier: C{unicode}
     360        @param maxItems: Optional limit on the number of retrieved items.
     361        @type maxItems: C{int}
     362        """
     363        request = _PubSubRequest(self.xmlstream, 'items', method='get')
     364        request.command['node'] = nodeIdentifier
     365        if maxItems:
     366            request.command["max_items"] = str(int(maxItems))
     367
    344368        def cb(iq):
    345369            items = []
     
    349373            return items
    350374
    351         request = Items(self.xmlstream, nodeIdentifier)
    352375        return request.send(service).addCallback(cb)
     376
     377
    353378
    354379class PubSubService(XMPPHandler, IQHandlerMixin):
  • wokkel/test/test_pubsub.py

    r17 r18  
    5151        self.protocol.connectionInitialized()
    5252
    53     def test_unsubscribe(self):
    54         """
    55         Test sending unsubscription request.
    56         """
    57         d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
    58                                       JID('user@example.org'))
    59 
    60         iq = self.stub.output[-1]
    61         self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
    62         self.assertEquals('set', iq.getAttribute('type'))
    63         self.assertEquals('pubsub', iq.pubsub.name)
    64         self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
    65         children = list(domish.generateElementsQNamed(iq.pubsub.children,
    66                                                       'unsubscribe', NS_PUBSUB))
    67         self.assertEquals(1, len(children))
    68         child = children[0]
    69         self.assertEquals('test', child['node'])
    70         self.assertEquals('user@example.org', child['jid'])
    71 
    72         self.stub.send(toResponse(iq, 'result'))
    73         return d
    7453
    7554    def test_event_items(self):
     
    10079        return d
    10180
     81
    10282    def test_event_delete(self):
    10383        """
     
    120100        return d
    121101
     102
    122103    def test_event_purge(self):
    123104        """
     
    141122
    142123
     124    def test_createNode(self):
     125        """
     126        Test sending create request.
     127        """
     128
     129        def cb(nodeIdentifier):
     130            self.assertEquals('test', nodeIdentifier)
     131
     132        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
     133        d.addCallback(cb)
     134
     135        iq = self.stub.output[-1]
     136        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     137        self.assertEquals('set', iq.getAttribute('type'))
     138        self.assertEquals('pubsub', iq.pubsub.name)
     139        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     140        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     141                                                      'create', NS_PUBSUB))
     142        self.assertEquals(1, len(children))
     143        child = children[0]
     144        self.assertEquals('test', child['node'])
     145
     146        response = toResponse(iq, 'result')
     147        self.stub.send(response)
     148        return d
     149
     150
     151    def test_createNodeInstant(self):
     152        """
     153        Test sending create request resulting in an instant node.
     154        """
     155
     156        def cb(nodeIdentifier):
     157            self.assertEquals('test', nodeIdentifier)
     158
     159        d = self.protocol.createNode(JID('pubsub.example.org'))
     160        d.addCallback(cb)
     161
     162        iq = self.stub.output[-1]
     163        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     164                                                      'create', NS_PUBSUB))
     165        child = children[0]
     166        self.assertFalse(child.hasAttribute('node'))
     167
     168        response = toResponse(iq, 'result')
     169        command = response.addElement((NS_PUBSUB, 'pubsub'))
     170        create = command.addElement('create')
     171        create['node'] = 'test'
     172        self.stub.send(response)
     173        return d
     174
     175
     176    def test_createNodeRenamed(self):
     177        """
     178        Test sending create request resulting in renamed node.
     179        """
     180
     181        def cb(nodeIdentifier):
     182            self.assertEquals('test2', nodeIdentifier)
     183
     184        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
     185        d.addCallback(cb)
     186
     187        iq = self.stub.output[-1]
     188        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     189                                                      'create', NS_PUBSUB))
     190        child = children[0]
     191        self.assertEquals('test', child['node'])
     192
     193        response = toResponse(iq, 'result')
     194        command = response.addElement((NS_PUBSUB, 'pubsub'))
     195        create = command.addElement('create')
     196        create['node'] = 'test2'
     197        self.stub.send(response)
     198        return d
     199
     200
     201    def test_deleteNode(self):
     202        """
     203        Test sending delete request.
     204        """
     205
     206        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
     207
     208        iq = self.stub.output[-1]
     209        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     210        self.assertEquals('set', iq.getAttribute('type'))
     211        self.assertEquals('pubsub', iq.pubsub.name)
     212        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     213        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     214                                                      'delete', NS_PUBSUB))
     215        self.assertEquals(1, len(children))
     216        child = children[0]
     217        self.assertEquals('test', child['node'])
     218
     219        response = toResponse(iq, 'result')
     220        self.stub.send(response)
     221        return d
     222
     223
     224    def test_publish(self):
     225        """
     226        Test sending publish request.
     227        """
     228
     229        item = pubsub.Item()
     230        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
     231
     232        iq = self.stub.output[-1]
     233        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     234        self.assertEquals('set', iq.getAttribute('type'))
     235        self.assertEquals('pubsub', iq.pubsub.name)
     236        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     237        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     238                                                      'publish', NS_PUBSUB))
     239        self.assertEquals(1, len(children))
     240        child = children[0]
     241        self.assertEquals('test', child['node'])
     242        items = list(domish.generateElementsQNamed(child.children,
     243                                                   'item', NS_PUBSUB))
     244        self.assertEquals(1, len(items))
     245        self.assertIdentical(item, items[0])
     246
     247        response = toResponse(iq, 'result')
     248        self.stub.send(response)
     249        return d
     250
     251
     252    def test_publishNoItems(self):
     253        """
     254        Test sending publish request without items.
     255        """
     256
     257        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
     258
     259        iq = self.stub.output[-1]
     260        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     261        self.assertEquals('set', iq.getAttribute('type'))
     262        self.assertEquals('pubsub', iq.pubsub.name)
     263        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     264        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     265                                                      'publish', NS_PUBSUB))
     266        self.assertEquals(1, len(children))
     267        child = children[0]
     268        self.assertEquals('test', child['node'])
     269
     270        response = toResponse(iq, 'result')
     271        self.stub.send(response)
     272        return d
     273
     274
     275    def test_subscribe(self):
     276        """
     277        Test sending subscription request.
     278        """
     279        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
     280                                      JID('user@example.org'))
     281
     282        iq = self.stub.output[-1]
     283        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     284        self.assertEquals('set', iq.getAttribute('type'))
     285        self.assertEquals('pubsub', iq.pubsub.name)
     286        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     287        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     288                                                      'subscribe', NS_PUBSUB))
     289        self.assertEquals(1, len(children))
     290        child = children[0]
     291        self.assertEquals('test', child['node'])
     292        self.assertEquals('user@example.org', child['jid'])
     293
     294        response = toResponse(iq, 'result')
     295        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
     296        subscription = pubsub.addElement('subscription')
     297        subscription['node'] = 'test'
     298        subscription['jid'] = 'user@example.org'
     299        subscription['subscription'] = 'subscribed'
     300        self.stub.send(response)
     301        return d
     302
     303
     304    def test_subscribePending(self):
     305        """
     306        Test sending subscription request that results in a pending
     307        subscription.
     308        """
     309        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
     310                                      JID('user@example.org'))
     311
     312        iq = self.stub.output[-1]
     313        response = toResponse(iq, 'result')
     314        command = response.addElement((NS_PUBSUB, 'pubsub'))
     315        subscription = command.addElement('subscription')
     316        subscription['node'] = 'test'
     317        subscription['jid'] = 'user@example.org'
     318        subscription['subscription'] = 'pending'
     319        self.stub.send(response)
     320        self.assertFailure(d, pubsub.SubscriptionPending)
     321        return d
     322
     323
     324    def test_subscribePending(self):
     325        """
     326        Test sending subscription request that results in an unconfigured
     327        subscription.
     328        """
     329        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
     330                                      JID('user@example.org'))
     331
     332        iq = self.stub.output[-1]
     333        response = toResponse(iq, 'result')
     334        command = response.addElement((NS_PUBSUB, 'pubsub'))
     335        subscription = command.addElement('subscription')
     336        subscription['node'] = 'test'
     337        subscription['jid'] = 'user@example.org'
     338        subscription['subscription'] = 'unconfigured'
     339        self.stub.send(response)
     340        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
     341        return d
     342
     343
     344    def test_unsubscribe(self):
     345        """
     346        Test sending unsubscription request.
     347        """
     348        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
     349                                      JID('user@example.org'))
     350
     351        iq = self.stub.output[-1]
     352        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     353        self.assertEquals('set', iq.getAttribute('type'))
     354        self.assertEquals('pubsub', iq.pubsub.name)
     355        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     356        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     357                                                      'unsubscribe', NS_PUBSUB))
     358        self.assertEquals(1, len(children))
     359        child = children[0]
     360        self.assertEquals('test', child['node'])
     361        self.assertEquals('user@example.org', child['jid'])
     362
     363        self.stub.send(toResponse(iq, 'result'))
     364        return d
     365
     366
    143367    def test_items(self):
    144368        """
     
    169393
    170394        return d
     395
     396
     397    def test_itemsMaxItems(self):
     398        """
     399        Test sending items request, with limit on the number of items.
     400        """
     401        def cb(items):
     402            self.assertEquals(2, len(items))
     403            self.assertEquals([item1, item2], items)
     404
     405        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
     406        d.addCallback(cb)
     407
     408        iq = self.stub.output[-1]
     409        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
     410        self.assertEquals('get', iq.getAttribute('type'))
     411        self.assertEquals('pubsub', iq.pubsub.name)
     412        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
     413        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     414                                                      'items', NS_PUBSUB))
     415        self.assertEquals(1, len(children))
     416        child = children[0]
     417        self.assertEquals('test', child['node'])
     418        self.assertEquals('2', child['max_items'])
     419
     420        response = toResponse(iq, 'result')
     421        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
     422        items['node'] = 'test'
     423        item1 = items.addElement('item')
     424        item1['id'] = 'item1'
     425        item2 = items.addElement('item')
     426        item2['id'] = 'item2'
     427
     428        self.stub.send(response)
     429
     430        return d
     431
     432
    171433
    172434class PubSubServiceTest(unittest.TestCase):
Note: See TracChangeset for help on using the changeset viewer.