changeset 153:753b8432460f

Work towards JEP-0060 1.8 - Remove subscription information from <affiliations/> result. - Add handling of <subscriptions/> entity use case. - Make <subscribe/> return <subscription/> instead of <entity/>. - Move <purge/> and <delete/> to owner namespace. - Don't use 'self' in interfaces.
author Ralph Meijer <ralphm@ik.nu>
date Sat, 06 May 2006 19:47:53 +0000
parents ea8b4189ae3b
children bd8e58c73370
files idavoll/backend.py idavoll/generic_backend.py idavoll/pubsub.py
diffstat 3 files changed, 69 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/idavoll/backend.py	Tue Dec 06 15:18:30 2005 +0000
+++ b/idavoll/backend.py	Sat May 06 19:47:53 2006 +0000
@@ -34,7 +34,7 @@
 class IBackendService(Interface):
     """ Interface to a backend service of a pubsub service. """
 
-    def __init__(self, storage):
+    def __init__(storage):
         """
         @param storage: L{storage} object.
         """
@@ -57,7 +57,7 @@
         @rtype: C{bool}
         """
 
-    def get_node_type(self, node_id):
+    def get_node_type(node_id):
         """ Return type of a node.
 
         @return: a deferred that returns either 'leaf' or 'collection'
@@ -69,7 +69,7 @@
         @return: a deferred that returns a C{list} of node ids.
         """
 
-    def get_node_meta_data(self, node_id):
+    def get_node_meta_data(node_id):
         """ Return meta data for a node.
 
         @return: a deferred that returns a C{list} of C{dict}s with the
@@ -79,7 +79,7 @@
 class INodeCreationService(Interface):
     """ A service for creating nodes """
 
-    def create_node(self, node_id, requestor):
+    def create_node(node_id, requestor):
         """ Create a node.
         
         @return: a deferred that fires when the node has been created.
@@ -88,7 +88,7 @@
 class INodeDeletionService(Interface):
     """ A service for deleting nodes. """
 
-    def register_pre_delete(self, pre_delete_fn):
+    def register_pre_delete(pre_delete_fn):
         """ Register a callback that is called just before a node deletion.
         
         The function C{pre_deleted_fn} is added to a list of functions
@@ -107,13 +107,13 @@
         deferred is returned in the list of deferreds.
         """
 
-    def get_subscribers(self, node_id):
+    def get_subscribers(node_id):
         """ Get node subscriber list.
         
         @return: a deferred that fires with the list of subscribers.
         """
 
-    def delete_node(self, node_id, requestor):
+    def delete_node(node_id, requestor):
         """ Delete a node.
         
         @return: a deferred that fires when the node has been deleted.
@@ -122,7 +122,7 @@
 class IPublishService(Interface):
     """ A service for publishing items to a node. """
 
-    def publish(self, node_id, items, requestor):
+    def publish(node_id, items, requestor):
         """ Publish items to a pubsub node.
         
         @return: a deferred that fires when the items have been published.
@@ -130,16 +130,16 @@
 class INotificationService(Interface):
     """ A service for notification of published items. """
 
-    def register_notifier(self, observerfn, *args, **kwargs):
+    def register_notifier(observerfn, *args, **kwargs):
         """ Register callback which is called for notification. """
 
-    def get_notification_list(self, node_id, items):
+    def get_notification_list(node_id, items):
         pass
 
 class ISubscriptionService(Interface):
     """ A service for managing subscriptions. """
 
-    def subscribe(self, node_id, subscriber, requestor):
+    def subscribe(node_id, subscriber, requestor):
         """ Request the subscription of an entity to a pubsub node.
 
         Depending on the node's configuration and possible business rules, the
@@ -151,7 +151,7 @@
         @return: a deferred that returns the subscription state
         """
 
-    def unsubscribe(self, node_id, subscriber, requestor):
+    def unsubscribe(node_id, subscriber, requestor):
         """ Cancel the subscription of an entity to a pubsub node.
 
         The subscription of C{subscriber} is removed from the list of
@@ -162,33 +162,42 @@
         @return: a deferred that fires when unsubscription is complete.
         """
 
+    def get_subscriptions(entity):
+        """ Report the list of current subscriptions with this pubsub service.
+
+        Report the list of the current subscriptions with all nodes within this
+        pubsub service, for the C{entity}.
+
+        @return: a deferred that returns the list of all current subscriptions
+                 as tuples C{(node_id, subscriber, subscription)}.
+        """
+
 class IAffiliationsService(Interface):
     """ A service for retrieving the affiliations with this pubsub service. """
 
-    def get_affiliations(self, entity):
+    def get_affiliations(entity):
         """ Report the list of current affiliations with this pubsub service.
 
         Report the list of the current affiliations with all nodes within this
-        pubsub service, along with subscriptions to such nodes, for the
-        C{entity}.
+        pubsub service, for the C{entity}.
 
         @return: a deferred that returns the list of all current affiliations
-        and subscriptions.
+                 as tuples C{(node_id, affiliation)}.
         """
 
 class IRetractionService(Interface):
     """ A service for retracting published items """
 
-    def retract_item(self, node_id, item_id, requestor):
+    def retract_item(node_id, item_id, requestor):
         """ Removes item in node from persistent storage """
 
-    def purge_node(self, node_id, requestor):
+    def purge_node(node_id, requestor):
         """ Removes all items in node from persistent storage """
 
 class IItemRetrievalService(Interface):
     """ A service for retrieving previously published items. """
 
-    def get_items(self, node_id, requestor, max_items=None, item_ids=[]):
+    def get_items(node_id, requestor, max_items=None, item_ids=[]):
         """ Retrieve items from persistent storage
 
         If C{max_items} is given, return the C{max_items} last published
--- a/idavoll/generic_backend.py	Tue Dec 06 15:18:30 2005 +0000
+++ b/idavoll/generic_backend.py	Sat May 06 19:47:53 2006 +0000
@@ -162,17 +162,15 @@
         d = node.add_subscription(subscriber, 'subscribed')
         d.addCallback(lambda _: 'subscribed')
         d.addErrback(self._get_subscription, node, subscriber)
-        d.addCallback(self._return_subscription, affiliation, node.id)
+        d.addCallback(self._return_subscription, node.id)
         return d
 
     def _get_subscription(self, failure, node, subscriber):
         failure.trap(storage.SubscriptionExists)
         return node.get_subscription(subscriber)
 
-    def _return_subscription(self, result, affiliation, node_id):
-        return {'affiliation': affiliation,
-                'node': node_id,
-                'state': result}
+    def _return_subscription(self, result, node_id):
+        return node_id, result
 
     def unsubscribe(self, node_id, subscriber, requestor):
         if subscriber.userhostJID() != requestor:
@@ -182,6 +180,9 @@
         d.addCallback(lambda node: node.remove_subscription(subscriber))
         return d
 
+    def get_subscriptions(self, entity):
+        return self.parent.storage.get_subscriptions(entity)
+
 class NodeCreationService(service.Service):
 
     implements(backend.INodeCreationService)
@@ -246,37 +247,7 @@
     implements(backend.IAffiliationsService)
 
     def get_affiliations(self, entity):
-        d1 = self.parent.storage.get_affiliations(entity)
-        d2 = self.parent.storage.get_subscriptions(entity)
-        d = defer.DeferredList([d1, d2], fireOnOneErrback=1, consumeErrors=1)
-        d.addErrback(lambda x: x.value[0])
-        d.addCallback(self._affiliations_result, entity)
-        return d
-
-    def _affiliations_result(self, result, entity):
-        affiliations = result[0][1]
-        subscriptions = result[1][1]
-
-        new_affiliations = {}
-
-        for node, affiliation in affiliations:
-            new_affiliations[(node, entity.full())] = {'node': node,
-                                                'jid': entity,
-                                                'affiliation': affiliation,
-                                                'subscription': None
-                                               }
-
-        for node, subscriber, subscription in subscriptions:
-            key = node, subscriber.full()
-            if new_affiliations.has_key(key):
-                new_affiliations[key]['subscription'] = subscription
-            else:
-                new_affiliations[key] = {'node': node,
-                                         'jid': subscriber,
-                                         'affiliation': None,
-                                         'subscription': subscription}
-
-        return new_affiliations.values()
+        return self.parent.storage.get_affiliations(entity)
 
 class ItemRetrievalService(service.Service):
 
--- a/idavoll/pubsub.py	Tue Dec 06 15:18:30 2005 +0000
+++ b/idavoll/pubsub.py	Sat May 06 19:47:53 2006 +0000
@@ -39,11 +39,12 @@
 PUBSUB_OPTIONS_SET = PUBSUB_SET + '/options'
 PUBSUB_CONFIGURE_GET = PUBSUB_OWNER_GET + '/configure'
 PUBSUB_CONFIGURE_SET = PUBSUB_OWNER_SET + '/configure'
+PUBSUB_SUBSCRIPTIONS = PUBSUB_GET + '/subscriptions'
 PUBSUB_AFFILIATIONS = PUBSUB_GET + '/affiliations'
 PUBSUB_ITEMS = PUBSUB_GET + '/items'
 PUBSUB_RETRACT = PUBSUB_SET + '/retract'
-PUBSUB_PURGE = PUBSUB_SET + '/purge'
-PUBSUB_DELETE = PUBSUB_SET + '/delete'
+PUBSUB_PURGE = PUBSUB_OWNER_SET + '/purge'
+PUBSUB_DELETE = PUBSUB_OWNER_SET + '/delete'
 
 class Error(Exception):
     pubsub_error = None
@@ -270,12 +271,14 @@
         xmlstream.addObserver(PUBSUB_UNSUBSCRIBE, self.onUnsubscribe)
         xmlstream.addObserver(PUBSUB_OPTIONS_GET, self.onOptionsGet)
         xmlstream.addObserver(PUBSUB_OPTIONS_SET, self.onOptionsSet)
+        xmlstream.addObserver(PUBSUB_SUBSCRIPTIONS, self.onSubscriptions)
     
     def get_disco_info(self, node):
         info = []
 
         if not node:
             info.append(disco.Feature(NS_PUBSUB + '#subscribe'))
+            info.append(disco.Feature(NS_PUBSUB + '#retrieve-subscriptions'))
 
         return defer.succeed(info)
 
@@ -295,12 +298,13 @@
         return d
 
     def return_subscription(self, result, subscriber):
+        node, state = result
+
         reply = domish.Element((NS_PUBSUB, "pubsub"))
-        entity = reply.addElement("entity")
-        entity["node"] = result["node"]
-        entity["jid"] = subscriber.full()
-        entity["affiliation"] = result["affiliation"] or 'none'
-        entity["subscription"] = result["state"]
+        subscription = reply.addElement("subscription")
+        subscription["node"] = nod
+        subscription["jid"] = subscriber.full()
+        subscription["subscription"] = state
         return [reply]
 
     def onUnsubscribe(self, iq):
@@ -328,6 +332,25 @@
     def _onOptionsSet(self, iq):
         raise OptionsUnavailable
 
+    def onSubscriptions(self, iq):
+        self.handler_wrapper(self._onSubscriptions, iq)
+
+    def _onSubscriptions(self, iq):
+        entity = jid.internJID(iq["from"]).userhostJID()
+        d = self.backend.get_subscriptions(entity)
+        d.addCallback(self._return_subscriptions_response, iq)
+        return d
+
+    def _return_subscriptions_response(self, result, iq):
+        reply = domish.Element((NS_PUBSUB, 'pubsub'))
+        subscriptions = reply.addElement('subscriptions')
+        for node, subscriber, state in result:
+            item = subscriptions.addElement('subscription')
+            item['node'] = node
+            item['jid'] = subscriber.full()
+            item['subscription'] = state
+        return [reply]
+
 components.registerAdapter(ComponentServiceFromSubscriptionService,
                            backend.ISubscriptionService,
                            component.IService)
@@ -472,12 +495,10 @@
     def _return_affiliations_response(self, result, iq):
         reply = domish.Element((NS_PUBSUB, 'pubsub'))
         affiliations = reply.addElement('affiliations')
-        for r in result:
-            entity = affiliations.addElement('entity')
-            entity['node'] = r['node']
-            entity['jid'] = r['jid'].full()
-            entity['affiliation'] = r['affiliation'] or 'none'
-            entity['subscription'] = r['subscription'] or 'none'
+        for node, affiliation in result:
+            item = affiliations.addElement('affiliation')
+            item['node'] = node
+            item['affiliation'] = affiliation
         return [reply]
 
 components.registerAdapter(ComponentServiceFromAffiliationsService,