diff -r 7740d56a1644 wokkel/disco.py
--- a/wokkel/disco.py Mon Jan 18 09:16:50 2010 +0100
+++ b/wokkel/disco.py Thu Jan 21 11:39:08 2010 +0100
@@ -495,10 +495,7 @@
"""
Gather results from a list of deferreds.
- Similar to L{defer.gatherResults}, but flattens the returned results,
- consumes errors after the first one and fires the errback of the
- returned deferred with the failure of the first deferred that fires its
- errback.
+ Similar to L{defer.gatherResults}, but flattens the returned results.
@param deferredList: List of deferreds for which the results should be
gathered.
@@ -512,13 +509,9 @@
results.extend(value)
return results
- def eb(failure):
- failure.trap(defer.FirstError)
- return failure.value.subFailure
-
d = defer.DeferredList(deferredList, fireOnOneErrback=1,
consumeErrors=1)
- d.addCallbacks(cb, eb)
+ d.addCallback(cb)
return d
diff -r 7740d56a1644 wokkel/pubsub.py
--- a/wokkel/pubsub.py Mon Jan 18 09:16:50 2010 +0100
+++ b/wokkel/pubsub.py Thu Jan 21 11:39:08 2010 +0100
@@ -1011,7 +1011,7 @@
@type pubSubFeatures: C{list} or C{None}
"""
- implements(IPubSubService)
+ implements(IPubSubService, disco.IDisco)
iqHandlers = {
'/*': '_onPubSubRequest',
@@ -1057,10 +1057,10 @@
self.xmlstream.addObserver(PUBSUB_REQUEST, self.handleRequest)
- def getDiscoInfo(self, requestor, target, nodeIdentifier):
- def toInfo(nodeInfo, info):
+ def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
+ def toInfo(nodeInfo):
if not nodeInfo:
- return info
+ return
(nodeType, metaData) = nodeInfo['type'], nodeInfo['meta-data']
info.append(disco.DiscoIdentity('pubsub', nodeType))
@@ -1080,7 +1080,7 @@
info.append(form)
- return info
+ return
info = []
@@ -1106,12 +1106,13 @@
for feature in features])
d = defer.maybeDeferred(getInfo, requestor, target, nodeIdentifier or '')
- d.addCallback(toInfo, info)
+ d.addCallback(toInfo)
d.addErrback(log.err)
+ d.addCallback(lambda _: info)
return d
- def getDiscoItems(self, requestor, target, nodeIdentifier):
+ def getDiscoItems(self, requestor, target, nodeIdentifier=''):
if self.hideNodes:
d = defer.succeed([])
elif self.resource is not None:
diff -r 7740d56a1644 wokkel/test/test_disco.py
--- a/wokkel/test/test_disco.py Mon Jan 18 09:16:50 2010 +0100
+++ b/wokkel/test/test_disco.py Thu Jan 21 11:39:08 2010 +0100
@@ -9,9 +9,10 @@
from twisted.internet import defer
from twisted.trial import unittest
+from twisted.words.protocols.jabber.error import StanzaError
from twisted.words.protocols.jabber.jid import JID
from twisted.words.protocols.jabber.xmlstream import toResponse
-from twisted.words.xish import domish
+from twisted.words.xish import domish, utility
from wokkel import data_form, disco
from wokkel.generic import parseXml
@@ -596,6 +597,46 @@
self.service = disco.DiscoHandler()
+ def test_connectionInitializedObserveInfo(self):
+ """
+ An observer for Disco Info requests is setup on stream initialization.
+ """
+ xml = """
+
+ """ % NS_DISCO_INFO
+
+ def handleRequest(iq):
+ called.append(iq)
+
+ called = []
+ self.service.xmlstream = utility.EventDispatcher()
+ self.service.handleRequest = handleRequest
+ self.service.connectionInitialized()
+ self.service.xmlstream.dispatch(parseXml(xml))
+ self.assertEqual(1, len(called))
+
+
+ def test_connectionInitializedObserveItems(self):
+ """
+ An observer for Disco Items requests is setup on stream initialization.
+ """
+ xml = """
+
+ """ % NS_DISCO_ITEMS
+
+ def handleRequest(iq):
+ called.append(iq)
+
+ called = []
+ self.service.xmlstream = utility.EventDispatcher()
+ self.service.handleRequest = handleRequest
+ self.service.connectionInitialized()
+ self.service.xmlstream.dispatch(parseXml(xml))
+ self.assertEqual(1, len(called))
+
+
def test_onDiscoInfo(self):
"""
C{onDiscoInfo} should process an info request and return a response.
@@ -661,6 +702,30 @@
return d
+ def test_onDiscoInfoWithNodeNoResults(self):
+ """
+ An info request for a node with no results returns items-not-found.
+ """
+ xml = """
+
+ """ % NS_DISCO_INFO
+
+ def cb(exc):
+ self.assertEquals('item-not-found', exc.condition)
+
+ def info(requestor, target, nodeIdentifier):
+ self.assertEqual('test', nodeIdentifier)
+
+ return defer.succeed([])
+
+ self.service.info = info
+ d = self.handleRequest(xml)
+ self.assertFailure(d, StanzaError)
+ d.addCallback(cb)
+ return d
+
+
def test_onDiscoItems(self):
"""
C{onDiscoItems} should process an items request and return a response.
diff -r 7740d56a1644 wokkel/test/test_pubsub.py
--- a/wokkel/test/test_pubsub.py Mon Jan 18 09:16:50 2010 +0100
+++ b/wokkel/test/test_pubsub.py Thu Jan 21 11:39:08 2010 +0100
@@ -1903,6 +1903,13 @@
verify.verifyObject(iwokkel.IPubSubService, self.service)
+ def test_interfaceIDisco(self):
+ """
+ Do instances of L{pubsub.PubSubService} provide L{iwokkel.IDisco}?
+ """
+ verify.verifyObject(iwokkel.IDisco, self.service)
+
+
def test_connectionMade(self):
"""
Verify setup of observers in L{pubsub.connectionMade}.
@@ -2009,6 +2016,42 @@
return d
+ def test_getDiscoInfoBadResponse(self):
+ """
+ If getInfo returns invalid response, it should be logged, then ignored.
+ """
+ def cb(info):
+ self.assertEquals([], info)
+ self.assertEqual(1, len(self.flushLoggedErrors(TypeError)))
+
+ def getInfo(requestor, target, nodeIdentifier):
+ return defer.succeed('bad response')
+
+ self.resource.getInfo = getInfo
+ d = self.service.getDiscoInfo(JID('user@example.org/home'),
+ JID('pubsub.example.org'), 'test')
+ d.addCallback(cb)
+ return d
+
+
+ def test_getDiscoInfoException(self):
+ """
+ If getInfo returns invalid response, it should be logged, then ignored.
+ """
+ def cb(info):
+ self.assertEquals([], info)
+ self.assertEqual(1, len(self.flushLoggedErrors(NotImplementedError)))
+
+ def getInfo(requestor, target, nodeIdentifier):
+ return defer.fail(NotImplementedError())
+
+ self.resource.getInfo = getInfo
+ d = self.service.getDiscoInfo(JID('user@example.org/home'),
+ JID('pubsub.example.org'), 'test')
+ d.addCallback(cb)
+ return d
+
+
def test_getDiscoItemsRoot(self):
"""
Test getDiscoItems on the root node.