Commits

Ralph Meijer committed 3e957d5

Undo code move from wokkel.xmppim to wokkel.im.

This also adds a new patch for defining Wokkel's version in wokkel.__version__
and defers the JID cleanup.

Comments (0)

Files changed (5)

c2s_stanza_handlers.patch

 # HG changeset patch
-# Parent 24c6e79ab1c449f41fd5d4c2cb843dc16efe2c59
+# Parent 8c6fa8ea95402e5c968f57e7fde2f8e249c11d12
 Add c2s protocol handlers for iq, message and presence stanzas.
 
 TODO:
  * Add docstrings.
  * Save last unavailable presence for future probes.
 
-diff -r 24c6e79ab1c4 doc/examples/client_service.tac
---- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/doc/examples/client_service.tac	Wed Mar 28 13:23:36 2012 +0200
+diff --git a/doc/examples/client_service.tac b/doc/examples/client_service.tac
+new file mode 100644
+--- /dev/null
++++ b/doc/examples/client_service.tac
 @@ -0,0 +1,75 @@
 +from twisted.application import service, strports
 +from twisted.internet import defer
 +
-+from wokkel import client, im
++from wokkel import client, xmppim
 +from wokkel.component import InternalComponent, Router
 +from wokkel.generic import FallbackHandler
 +from wokkel.ping import PingHandler
-+from wokkel.im import RosterItem
++from wokkel.xmppim import RosterItem
 +
 +from twisted.words.protocols.jabber.jid import internJID as JID
 +
 +accounts = set(roster.keys())
 +
 +
-+class StaticRoster(im.RosterServerProtocol):
++class StaticRoster(xmppim.RosterServerProtocol):
 +
 +    def __init__(self, roster):
-+        im.RosterServerProtocol.__init__(self)
++        xmppim.RosterServerProtocol.__init__(self)
 +        self.roster = roster
 +
 +    def getRoster(self, request):
 +sessionManager = client.SessionManager(domain, accounts)
 +sessionManager.setHandlerParent(component)
 +
-+im.AccountIQHandler(sessionManager).setHandlerParent(component)
-+im.AccountMessageHandler(sessionManager).setHandlerParent(component)
-+im.PresenceServerHandler(sessionManager, domain, roster).setHandlerParent(component)
++xmppim.AccountIQHandler(sessionManager).setHandlerParent(component)
++xmppim.AccountMessageHandler(sessionManager).setHandlerParent(component)
++xmppim.PresenceServerHandler(sessionManager, domain, roster).setHandlerParent(component)
 +FallbackHandler().setHandlerParent(component)
 +StaticRoster(roster).setHandlerParent(component)
 +PingHandler().setHandlerParent(component)
 +c2sService.setServiceParent(application)
 +
 +sessionManager.connectionManager = c2sFactory
-diff -r 24c6e79ab1c4 wokkel/im.py
---- a/wokkel/im.py	Wed Mar 28 13:22:34 2012 +0200
-+++ b/wokkel/im.py	Wed Mar 28 13:23:36 2012 +0200
-@@ -10,7 +10,10 @@
- U{RFC 6121<http://www.xmpp.org/rfcs/rfc6121.html>} (XMPP IM).
- """
+diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_xmppim.py
+--- a/wokkel/test/test_xmppim.py
++++ b/wokkel/test/test_xmppim.py
+@@ -13,7 +13,7 @@
+ from twisted.words.xish import domish, utility
+ 
+ from wokkel import xmppim
+-from wokkel.generic import ErrorStanza, parseXml
++from wokkel.generic import ErrorStanza, Stanza, parseXml
+ from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
+ 
+ NS_XML = 'http://www.w3.org/XML/1998/namespace'
+@@ -1333,6 +1333,82 @@
+ 
+ 
+ 
++class AccountIQHandlerTest(unittest.TestCase):
++    """
++    Tests for L{xmppim.AccountIQHandler}.
++    """
++
++    def setUp(self):
++        self.stub = XmlStreamStub()
++        self.protocol = xmppim.AccountIQHandler(None)
++        self.protocol.makeConnection(self.stub.xmlstream)
++        self.protocol.connectionInitialized()
++
++
++    def test_onIQNotUser(self):
++        """
++        IQs to JIDs without local part are ignored.
++        """
++        xml = """
++          <iq to='example.org'>
++            <query xmlns='jabber:iq:version'/>
++          </iq>
++        """
++
++        iq = parseXml(xml)
++        self.stub.send(iq)
++
++        self.assertFalse(getattr(iq, 'handled'))
++
++
++
++class AccountMessageHandlerTest(unittest.TestCase):
++    """
++    Tests for L{xmppim.AccountMessageHandler}.
++    """
++
++    def setUp(self):
++        self.stub = XmlStreamStub()
++        self.protocol = xmppim.AccountMessageHandler(None)
++        self.protocol.makeConnection(self.stub.xmlstream)
++        self.protocol.connectionInitialized()
++
++
++    def test_onMessageNotUser(self):
++        """
++        Messages to JIDs without local part are ignored.
++        """
++        xml = """
++          <message to='example.org'>
++            <body>Hello</body>
++          </message>
++        """
++
++        message = parseXml(xml)
++        self.stub.send(message)
++
++        self.assertFalse(getattr(message, 'handled'))
++
++
++
++class ClonePresenceTest(unittest.TestCase):
++    """
++    Tests for L{xmppim.clonePresence}.
++    """
++
++    def test_rootElement(self):
++        """
++        The copied presence stanza is not identical, but renders identically.
++        """
++        originalElement = domish.Element((None, 'presence'))
++        stanza = Stanza.fromElement(originalElement)
++        copyElement = xmppim.clonePresence(stanza)
++
++        self.assertNotIdentical(copyElement, originalElement)
++        self.assertEquals(copyElement.toXml(), originalElement.toXml())
++
++
++
+ class RosterServerProtocolTest(unittest.TestCase, TestableRequestHandlerMixin):
+     """
+     Tests for L{xmppim.RosterServerProtocol}.
+diff --git a/wokkel/xmppim.py b/wokkel/xmppim.py
+--- a/wokkel/xmppim.py
++++ b/wokkel/xmppim.py
+@@ -12,7 +12,10 @@
+ 
+ import warnings
  
 +import copy
 +
  from twisted.internet import defer
 +from twisted.python import log
  from twisted.words.protocols.jabber import error
- from twisted.words.protocols.jabber import jid
+ from twisted.words.protocols.jabber.jid import JID
  from twisted.words.xish import domish
-@@ -179,10 +182,7 @@
+@@ -408,10 +411,7 @@
  
  
  
          stanza = Stanza.fromElement(element)
  
          presenceType = stanza.stanzaType or 'available'
-@@ -192,14 +192,22 @@
+@@ -421,14 +421,22 @@
          except KeyError:
              return
  
  
  
  
-@@ -582,6 +590,440 @@
+@@ -1067,6 +1075,440 @@
  
  
  
 +            return
 +
 +        try:
-+            recipient = jid.internJID(iq['to'])
++            recipient = JID(iq['to'])
 +        except KeyError:
 +            return
 +
 +            return
 +
 +        try:
-+            recipient = jid.internJID(message['to'])
++            recipient = JID(message['to'])
 +        except KeyError:
 +            return
 +
 +            if otherResource == fromJID.resource:
 +                continue
 +
-+            resourceJID = jid.JID(tuple=(fromJID.user,
-+                                         fromJID.host,
-+                                         otherResource))
++            resourceJID = JID(tuple=(fromJID.user,
++                                     fromJID.host,
++                                     otherResource))
 +            outPresence = clonePresence(presence)
 +            outPresence['to'] = resourceJID.full()
 +            self.sessionManager.deliverStanza(outPresence, resourceJID)
 +                if item.entity.user in self.presences:
 +                    # broadcast to contact's available resources
 +                    for itemResource in self.presences[item.entity.user]:
-+                        resourceJID = jid.JID(tuple=(item.entity.user,
-+                                                     item.entity.host,
-+                                                     itemResource))
++                        resourceJID = JID(tuple=(item.entity.user,
++                                                 item.entity.host,
++                                                 itemResource))
 +                        self.sessionManager.deliverStanza(outPresence,
 +                                                          resourceJID)
 +            else:
 +
 +        if toJID.user in self.presences:
 +            for resource in self.presences[toJID.user]:
-+                resourceJID = jid.JID(tuple=(toJID.user,
-+                                             toJID.host,
-+                                             resource))
++                resourceJID = JID(tuple=(toJID.user,
++                                         toJID.host,
++                                         resource))
 +                self.sessionManager.deliverStanza(presence.element, resourceJID)
 +            self.remotePresences[toJID.user][fromJID] = presence
 +        else:
  class RosterServerProtocol(XMPPHandler, IQHandlerMixin):
      """
      XMPP subprotocol handler for the roster, server side.
-diff -r 24c6e79ab1c4 wokkel/test/test_im.py
---- a/wokkel/test/test_im.py	Wed Mar 28 13:22:34 2012 +0200
-+++ b/wokkel/test/test_im.py	Wed Mar 28 13:23:36 2012 +0200
-@@ -13,7 +13,7 @@
- from twisted.words.xish import domish, utility
- 
- from wokkel import im
--from wokkel.generic import ErrorStanza, parseXml
-+from wokkel.generic import ErrorStanza, Stanza, parseXml
- from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
- 
- NS_XML = 'http://www.w3.org/XML/1998/namespace'
-@@ -846,6 +846,82 @@
- 
- 
- 
-+class AccountIQHandlerTest(unittest.TestCase):
-+    """
-+    Tests for L{im.AccountIQHandler}.
-+    """
-+
-+    def setUp(self):
-+        self.stub = XmlStreamStub()
-+        self.protocol = im.AccountIQHandler(None)
-+        self.protocol.makeConnection(self.stub.xmlstream)
-+        self.protocol.connectionInitialized()
-+
-+
-+    def test_onIQNotUser(self):
-+        """
-+        IQs to JIDs without local part are ignored.
-+        """
-+        xml = """
-+          <iq to='example.org'>
-+            <query xmlns='jabber:iq:version'/>
-+          </iq>
-+        """
-+
-+        iq = parseXml(xml)
-+        self.stub.send(iq)
-+
-+        self.assertFalse(getattr(iq, 'handled'))
-+
-+
-+
-+class AccountMessageHandlerTest(unittest.TestCase):
-+    """
-+    Tests for L{im.AccountMessageHandler}.
-+    """
-+
-+    def setUp(self):
-+        self.stub = XmlStreamStub()
-+        self.protocol = im.AccountMessageHandler(None)
-+        self.protocol.makeConnection(self.stub.xmlstream)
-+        self.protocol.connectionInitialized()
-+
-+
-+    def test_onMessageNotUser(self):
-+        """
-+        Messages to JIDs without local part are ignored.
-+        """
-+        xml = """
-+          <message to='example.org'>
-+            <body>Hello</body>
-+          </message>
-+        """
-+
-+        message = parseXml(xml)
-+        self.stub.send(message)
-+
-+        self.assertFalse(getattr(message, 'handled'))
-+
-+
-+
-+class ClonePresenceTest(unittest.TestCase):
-+    """
-+    Tests for L{im.clonePresence}.
-+    """
-+
-+    def test_rootElement(self):
-+        """
-+        The copied presence stanza is not identical, but renders identically.
-+        """
-+        originalElement = domish.Element((None, 'presence'))
-+        stanza = Stanza.fromElement(originalElement)
-+        copyElement = im.clonePresence(stanza)
-+
-+        self.assertNotIdentical(copyElement, originalElement)
-+        self.assertEquals(copyElement.toXml(), originalElement.toXml())
-+
-+
-+
- class RosterServerProtocolTest(unittest.TestCase, TestableRequestHandlerMixin):
-     """
-     Tests for L{im.RosterServerProtocol}.

copy_xmppim.patch

-# HG changeset patch
-# Parent 4ce55e7a3bb2f881333a4c61e215ffd2e3248695
-
-diff --git a/wokkel/xmppim.py b/wokkel/im.py
-copy from wokkel/xmppim.py
-copy to wokkel/im.py
---- a/wokkel/xmppim.py
-+++ b/wokkel/im.py
-@@ -22,234 +22,6 @@
- NS_XML = 'http://www.w3.org/XML/1998/namespace'
- NS_ROSTER = 'jabber:iq:roster'
- 
--class Presence(domish.Element):
--    def __init__(self, to=None, type=None):
--        domish.Element.__init__(self, (None, "presence"))
--        if type:
--            self["type"] = type
--
--        if to is not None:
--            self["to"] = to.full()
--
--class AvailablePresence(Presence):
--    def __init__(self, to=None, show=None, statuses=None, priority=0):
--        Presence.__init__(self, to, type=None)
--
--        if show in ['away', 'xa', 'chat', 'dnd']:
--            self.addElement('show', content=show)
--
--        if statuses is not None:
--            for lang, status in statuses.iteritems():
--                s = self.addElement('status', content=status)
--                if lang:
--                    s[(NS_XML, "lang")] = lang
--
--        if priority != 0:
--            self.addElement('priority', content=unicode(int(priority)))
--
--class UnavailablePresence(Presence):
--    def __init__(self, to=None, statuses=None):
--        Presence.__init__(self, to, type='unavailable')
--
--        if statuses is not None:
--            for lang, status in statuses.iteritems():
--                s = self.addElement('status', content=status)
--                if lang:
--                    s[(NS_XML, "lang")] = lang
--
--class PresenceClientProtocol(XMPPHandler):
--
--    def connectionInitialized(self):
--        self.xmlstream.addObserver('/presence', self._onPresence)
--
--    def _getStatuses(self, presence):
--        statuses = {}
--        for element in presence.elements():
--            if element.name == 'status':
--                lang = element.getAttribute((NS_XML, 'lang'))
--                text = unicode(element)
--                statuses[lang] = text
--        return statuses
--
--    def _onPresence(self, presence):
--        type = presence.getAttribute("type", "available")
--        try:
--            handler = getattr(self, '_onPresence%s' % (type.capitalize()))
--        except AttributeError:
--            return
--        else:
--            handler(presence)
--
--    def _onPresenceAvailable(self, presence):
--        entity = JID(presence["from"])
--
--        show = unicode(presence.show or '')
--        if show not in ['away', 'xa', 'chat', 'dnd']:
--            show = None
--
--        statuses = self._getStatuses(presence)
--
--        try:
--            priority = int(unicode(presence.priority or '')) or 0
--        except ValueError:
--            priority = 0
--
--        self.availableReceived(entity, show, statuses, priority)
--
--    def _onPresenceUnavailable(self, presence):
--        entity = JID(presence["from"])
--
--        statuses = self._getStatuses(presence)
--
--        self.unavailableReceived(entity, statuses)
--
--    def _onPresenceSubscribed(self, presence):
--        self.subscribedReceived(JID(presence["from"]))
--
--    def _onPresenceUnsubscribed(self, presence):
--        self.unsubscribedReceived(JID(presence["from"]))
--
--    def _onPresenceSubscribe(self, presence):
--        self.subscribeReceived(JID(presence["from"]))
--
--    def _onPresenceUnsubscribe(self, presence):
--        self.unsubscribeReceived(JID(presence["from"]))
--
--
--    def availableReceived(self, entity, show=None, statuses=None, priority=0):
--        """
--        Available presence was received.
--
--        @param entity: entity from which the presence was received.
--        @type entity: {JID}
--        @param show: detailed presence information. One of C{'away'}, C{'xa'},
--                     C{'chat'}, C{'dnd'} or C{None}.
--        @type show: C{str} or C{NoneType}
--        @param statuses: dictionary of natural language descriptions of the
--                         availability status, keyed by the language
--                         descriptor. A status without a language
--                         specified, is keyed with C{None}.
--        @type statuses: C{dict}
--        @param priority: priority level of the resource.
--        @type priority: C{int}
--        """
--
--    def unavailableReceived(self, entity, statuses=None):
--        """
--        Unavailable presence was received.
--
--        @param entity: entity from which the presence was received.
--        @type entity: {JID}
--        @param statuses: dictionary of natural language descriptions of the
--                         availability status, keyed by the language
--                         descriptor. A status without a language
--                         specified, is keyed with C{None}.
--        @type statuses: C{dict}
--        """
--
--    def subscribedReceived(self, entity):
--        """
--        Subscription approval confirmation was received.
--
--        @param entity: entity from which the confirmation was received.
--        @type entity: {JID}
--        """
--
--    def unsubscribedReceived(self, entity):
--        """
--        Unsubscription confirmation was received.
--
--        @param entity: entity from which the confirmation was received.
--        @type entity: {JID}
--        """
--
--    def subscribeReceived(self, entity):
--        """
--        Subscription request was received.
--
--        @param entity: entity from which the request was received.
--        @type entity: {JID}
--        """
--
--    def unsubscribeReceived(self, entity):
--        """
--        Unsubscription request was received.
--
--        @param entity: entity from which the request was received.
--        @type entity: {JID}
--        """
--
--    def available(self, entity=None, show=None, statuses=None, priority=0):
--        """
--        Send available presence.
--
--        @param entity: optional entity to which the presence should be sent.
--        @type entity: {JID}
--        @param show: optional detailed presence information. One of C{'away'},
--                     C{'xa'}, C{'chat'}, C{'dnd'}.
--        @type show: C{str}
--        @param statuses: dictionary of natural language descriptions of the
--                         availability status, keyed by the language
--                         descriptor. A status without a language
--                         specified, is keyed with C{None}.
--        @type statuses: C{dict}
--        @param priority: priority level of the resource.
--        @type priority: C{int}
--        """
--        self.send(AvailablePresence(entity, show, statuses, priority))
--
--    def unavailable(self, entity=None, statuses=None):
--        """
--        Send unavailable presence.
--
--        @param entity: optional entity to which the presence should be sent.
--        @type entity: {JID}
--        @param statuses: dictionary of natural language descriptions of the
--                         availability status, keyed by the language
--                         descriptor. A status without a language
--                         specified, is keyed with C{None}.
--        @type statuses: C{dict}
--        """
--        self.send(UnavailablePresence(entity, statuses))
--
--    def subscribe(self, entity):
--        """
--        Send subscription request
--
--        @param entity: entity to subscribe to.
--        @type entity: {JID}
--        """
--        self.send(Presence(to=entity, type='subscribe'))
--
--    def unsubscribe(self, entity):
--        """
--        Send unsubscription request
--
--        @param entity: entity to unsubscribe from.
--        @type entity: {JID}
--        """
--        self.send(Presence(to=entity, type='unsubscribe'))
--
--    def subscribed(self, entity):
--        """
--        Send subscription confirmation.
--
--        @param entity: entity that subscribed.
--        @type entity: {JID}
--        """
--        self.send(Presence(to=entity, type='subscribed'))
--
--    def unsubscribed(self, entity):
--        """
--        Send unsubscription confirmation.
--
--        @param entity: entity that unsubscribed.
--        @type entity: {JID}
--        """
--        self.send(Presence(to=entity, type='unsubscribed'))
--
--
--
- class BasePresence(Stanza):
-     """
-     Stanza of kind presence.
-@@ -633,6 +405,7 @@
-         self.groups = set()
- 
- 
-+
- class RosterClientProtocol(XMPPHandler):
-     """
-     Client side XMPP roster protocol.
-@@ -642,6 +415,7 @@
-         ROSTER_SET = "/iq[@type='set']/query[@xmlns='%s']" % NS_ROSTER
-         self.xmlstream.addObserver(ROSTER_SET, self._onRosterSet)
- 
-+
-     def _parseRosterItem(self, element):
-         jid = JID(element['jid'])
-         item = RosterItem(jid)
-@@ -656,6 +430,7 @@
- 
-         return item
- 
-+
-     def getRoster(self):
-         """
-         Retrieve contact list.
-@@ -711,6 +486,7 @@
-             item = self._parseRosterItem(iq.query.item)
-             self.onRosterSet(item)
- 
-+
-     def onRosterSet(self, item):
-         """
-         Called when a roster push for a new or update item was received.
-@@ -719,6 +495,7 @@
-         @type item: L{RosterItem}
-         """
- 
-+
-     def onRosterRemove(self, entity):
-         """
-         Called when a roster push for the removal of an item was received.
-@@ -764,34 +541,3 @@
-             element.addElement('subject', content=self.subject)
- 
-         return element
--
--
--
--class MessageProtocol(XMPPHandler):
--    """
--    Generic XMPP subprotocol handler for incoming message stanzas.
--    """
--
--    messageTypes = None, 'normal', 'chat', 'headline', 'groupchat'
--
--    def connectionInitialized(self):
--        self.xmlstream.addObserver("/message", self._onMessage)
--
--    def _onMessage(self, message):
--        if message.handled:
--            return
--
--        messageType = message.getAttribute("type")
--
--        if messageType == 'error':
--            return
--
--        if messageType not in self.messageTypes:
--            message["type"] = 'normal'
--
--        self.onMessage(message)
--
--    def onMessage(self, message):
--        """
--        Called when a message stanza was received.
--        """
-diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_im.py
-copy from wokkel/test/test_xmppim.py
-copy to wokkel/test/test_im.py
---- a/wokkel/test/test_xmppim.py
-+++ b/wokkel/test/test_im.py
-@@ -2,7 +2,7 @@
- # See LICENSE for details
- 
- """
--Tests for L{wokkel.xmppim}.
-+Tests for L{wokkel.im}.
- """
- 
- from twisted.internet import defer
-@@ -11,74 +11,13 @@
- from twisted.words.protocols.jabber.xmlstream import toResponse
- from twisted.words.xish import domish, utility
- 
--from wokkel import xmppim
-+from wokkel import im
- from wokkel.generic import ErrorStanza, parseXml
- from wokkel.test.helpers import XmlStreamStub
- 
- NS_XML = 'http://www.w3.org/XML/1998/namespace'
- NS_ROSTER = 'jabber:iq:roster'
- 
--class PresenceClientProtocolTest(unittest.TestCase):
--    def setUp(self):
--        self.output = []
--        self.protocol = xmppim.PresenceClientProtocol()
--        self.protocol.parent = self
--
--    def send(self, obj):
--        self.output.append(obj)
--
--    def test_unavailableDirected(self):
--        """
--        Test sending of directed unavailable presence broadcast.
--        """
--
--        self.protocol.unavailable(JID('user@example.com'))
--        presence = self.output[-1]
--        self.assertEquals("presence", presence.name)
--        self.assertEquals(None, presence.uri)
--        self.assertEquals("user@example.com", presence.getAttribute('to'))
--        self.assertEquals("unavailable", presence.getAttribute('type'))
--
--    def test_unavailableWithStatus(self):
--        """
--        Test sending of directed unavailable presence broadcast with status.
--        """
--
--        self.protocol.unavailable(JID('user@example.com'),
--                                  {None: 'Disconnected'})
--        presence = self.output[-1]
--        self.assertEquals("presence", presence.name)
--        self.assertEquals(None, presence.uri)
--        self.assertEquals("user@example.com", presence.getAttribute('to'))
--        self.assertEquals("unavailable", presence.getAttribute('type'))
--        self.assertEquals("Disconnected", unicode(presence.status))
--
--    def test_unavailableBroadcast(self):
--        """
--        Test sending of unavailable presence broadcast.
--        """
--
--        self.protocol.unavailable(None)
--        presence = self.output[-1]
--        self.assertEquals("presence", presence.name)
--        self.assertEquals(None, presence.uri)
--        self.assertEquals(None, presence.getAttribute('to'))
--        self.assertEquals("unavailable", presence.getAttribute('type'))
--
--    def test_unavailableBroadcastNoEntityParameter(self):
--        """
--        Test sending of unavailable presence broadcast by not passing entity.
--        """
--
--        self.protocol.unavailable()
--        presence = self.output[-1]
--        self.assertEquals("presence", presence.name)
--        self.assertEquals(None, presence.uri)
--        self.assertEquals(None, presence.getAttribute('to'))
--        self.assertEquals("unavailable", presence.getAttribute('type'))
--
--
--
- class AvailabilityPresenceTest(unittest.TestCase):
- 
-     def test_fromElement(self):
-@@ -89,7 +28,7 @@
-                  </presence>
-               """
- 
--        presence = xmppim.AvailabilityPresence.fromElement(parseXml(xml))
-+        presence = im.AvailabilityPresence.fromElement(parseXml(xml))
-         self.assertEquals(JID('user@example.org'), presence.sender)
-         self.assertEquals(JID('user@example.com'), presence.recipient)
-         self.assertTrue(presence.available)
-@@ -98,14 +37,15 @@
-         self.assertEquals(50, presence.priority)
- 
- 
-+
- class PresenceProtocolTest(unittest.TestCase):
-     """
--    Tests for L{xmppim.PresenceProtocol}
-+    Tests for L{im.PresenceProtocol}
-     """
- 
-     def setUp(self):
-         self.output = []
--        self.protocol = xmppim.PresenceProtocol()
-+        self.protocol = im.PresenceProtocol()
-         self.protocol.parent = self
-         self.protocol.xmlstream = utility.EventDispatcher()
-         self.protocol.connectionInitialized()
-@@ -122,7 +62,7 @@
-         xml = """<presence type="error"/>"""
- 
-         def errorReceived(error):
--            xmppim.PresenceProtocol.errorReceived(self.protocol, error)
-+            im.PresenceProtocol.errorReceived(self.protocol, error)
-             try:
-                 self.assertIsInstance(error, ErrorStanza)
-             except:
-@@ -143,9 +83,9 @@
-         xml = """<presence/>"""
- 
-         def availableReceived(presence):
--            xmppim.PresenceProtocol.availableReceived(self.protocol, presence)
-+            im.PresenceProtocol.availableReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.AvailabilityPresence)
-+                self.assertIsInstance(presence, im.AvailabilityPresence)
-             except:
-                 d.errback()
-             else:
-@@ -164,9 +104,9 @@
-         xml = """<presence type='unavailable'/>"""
- 
-         def unavailableReceived(presence):
--            xmppim.PresenceProtocol.unavailableReceived(self.protocol, presence)
-+            im.PresenceProtocol.unavailableReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.AvailabilityPresence)
-+                self.assertIsInstance(presence, im.AvailabilityPresence)
-             except:
-                 d.errback()
-             else:
-@@ -185,9 +125,9 @@
-         xml = """<presence type='subscribe'/>"""
- 
-         def subscribeReceived(presence):
--            xmppim.PresenceProtocol.subscribeReceived(self.protocol, presence)
-+            im.PresenceProtocol.subscribeReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.SubscriptionPresence)
-+                self.assertIsInstance(presence, im.SubscriptionPresence)
-             except:
-                 d.errback()
-             else:
-@@ -206,9 +146,9 @@
-         xml = """<presence type='unsubscribe'/>"""
- 
-         def unsubscribeReceived(presence):
--            xmppim.PresenceProtocol.unsubscribeReceived(self.protocol, presence)
-+            im.PresenceProtocol.unsubscribeReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.SubscriptionPresence)
-+                self.assertIsInstance(presence, im.SubscriptionPresence)
-             except:
-                 d.errback()
-             else:
-@@ -227,9 +167,9 @@
-         xml = """<presence type='subscribed'/>"""
- 
-         def subscribedReceived(presence):
--            xmppim.PresenceProtocol.subscribedReceived(self.protocol, presence)
-+            im.PresenceProtocol.subscribedReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.SubscriptionPresence)
-+                self.assertIsInstance(presence, im.SubscriptionPresence)
-             except:
-                 d.errback()
-             else:
-@@ -248,10 +188,10 @@
-         xml = """<presence type='unsubscribed'/>"""
- 
-         def unsubscribedReceived(presence):
--            xmppim.PresenceProtocol.unsubscribedReceived(self.protocol,
-+            im.PresenceProtocol.unsubscribedReceived(self.protocol,
-                                                          presence)
-             try:
--                self.assertIsInstance(presence, xmppim.SubscriptionPresence)
-+                self.assertIsInstance(presence, im.SubscriptionPresence)
-             except:
-                 d.errback()
-             else:
-@@ -270,9 +210,9 @@
-         xml = """<presence type='probe'/>"""
- 
-         def probeReceived(presence):
--            xmppim.PresenceProtocol.probeReceived(self.protocol, presence)
-+            im.PresenceProtocol.probeReceived(self.protocol, presence)
-             try:
--                self.assertIsInstance(presence, xmppim.ProbePresence)
-+                self.assertIsInstance(presence, im.ProbePresence)
-             except:
-                 d.errback()
-             else:
-@@ -451,12 +391,12 @@
- 
- class RosterClientProtocolTest(unittest.TestCase):
-     """
--    Tests for L{xmppim.RosterClientProtocol}.
-+    Tests for L{im.RosterClientProtocol}.
-     """
- 
-     def setUp(self):
-         self.stub = XmlStreamStub()
--        self.protocol = xmppim.RosterClientProtocol()
-+        self.protocol = im.RosterClientProtocol()
-         self.protocol.xmlstream = self.stub.xmlstream
-         self.protocol.connectionInitialized()
- 

roster_server.patch

  * Use `dict` instead of `list` as return value of `getRoster`.
  * Add support for roster sets?
 
-diff -r e3c41b054210 wokkel/im.py
---- a/wokkel/im.py	Wed Oct 05 09:32:22 2011 +0200
-+++ b/wokkel/im.py	Wed Oct 05 09:38:26 2011 +0200
-@@ -23,6 +23,7 @@
- NS_ROSTER = 'jabber:iq:roster'
- 
- XPATH_ROSTER_SET = "/iq[@type='set']/query[@xmlns='%s']" % NS_ROSTER
-+XPATH_ROSTER_GET = "/iq[@type='get']/query[@xmlns='%s']" % NS_ROSTER
- 
- 
- 
-@@ -549,3 +550,40 @@
-         @param entity: The entity for which the roster item has been removed.
-         @type entity: L{jid.JID}
-         """
-+
-+
-+
-+class RosterServerProtocol(XMPPHandler, IQHandlerMixin):
-+    """
-+    XMPP subprotocol handler for the roster, server side.
-+    """
-+
-+    iqHandlers = {
-+            XPATH_ROSTER_GET: '_onRosterGet',
-+            # XPATH_ROSTER_SET: '_onRosterSet',
-+            }
-+
-+    def connectionInitialized(self):
-+        self.xmlstream.addObserver(XPATH_ROSTER_GET, self.handleRequest)
-+        self.xmlstream.addObserver(XPATH_ROSTER_SET, self.handleRequest)
-+
-+
-+    def _toRosterReply(self, roster, request):
-+        response = domish.Element((NS_ROSTER, 'query'))
-+
-+        for item in roster:
-+            response.addChild(item.toElement())
-+
-+        return response
-+
-+
-+    def _onRosterGet(self, iq):
-+        request = Stanza.fromElement(iq)
-+
-+        d = self.getRoster(request)
-+        d.addCallback(self._toRosterReply, request)
-+        return d
-+
-+
-+    def getRoster(self, entity):
-+        raise NotImplementedError()
-diff -r e3c41b054210 wokkel/test/test_im.py
---- a/wokkel/test/test_im.py	Wed Oct 05 09:32:22 2011 +0200
-+++ b/wokkel/test/test_im.py	Wed Oct 05 09:38:26 2011 +0200
-@@ -844,3 +844,80 @@
+diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_xmppim.py
+--- a/wokkel/test/test_xmppim.py
++++ b/wokkel/test/test_xmppim.py
+@@ -1330,3 +1330,81 @@
+         d = self.handleRequest(xml)
          d.addCallback(cb)
          return d
- 
++
 +
 +
 +class RosterServerProtocolTest(unittest.TestCase, TestableRequestHandlerMixin):
 +    """
-+    Tests for L{im.RosterServerProtocol}.
++    Tests for L{xmppim.RosterServerProtocol}.
 +    """
 +
 +    def setUp(self):
 +        self.stub = XmlStreamStub()
-+        self.service = im.RosterServerProtocol()
++        self.service = xmppim.RosterServerProtocol()
 +        self.service.makeConnection(self.stub.xmlstream)
 +        self.service.connectionInitialized()
 +
 +
 +        def getRoster(request):
 +            self.assertEqual(JID('user@example.org'), request.sender)
-+            item = im.RosterItem(JID('other@example.org'), True, False,
++            item = xmppim.RosterItem(JID('other@example.org'), True, False,
 +                                 'The User')
 +            return defer.succeed([item])
 +
 +        d = self.handleRequest(xml)
 +        self.assertFailure(d, NotImplementedError)
 +        return d
+diff --git a/wokkel/xmppim.py b/wokkel/xmppim.py
+--- a/wokkel/xmppim.py
++++ b/wokkel/xmppim.py
+@@ -25,6 +25,7 @@
+ NS_ROSTER = 'jabber:iq:roster'
+ 
+ XPATH_ROSTER_SET = "/iq[@type='set']/query[@xmlns='%s']" % NS_ROSTER
++XPATH_ROSTER_GET = "/iq[@type='get']/query[@xmlns='%s']" % NS_ROSTER
+ 
+ 
+ 
+@@ -1063,3 +1064,40 @@
+         """
+         Called when a message stanza was received.
+         """
++
++
++
++class RosterServerProtocol(XMPPHandler, IQHandlerMixin):
++    """
++    XMPP subprotocol handler for the roster, server side.
++    """
++
++    iqHandlers = {
++            XPATH_ROSTER_GET: '_onRosterGet',
++            # XPATH_ROSTER_SET: '_onRosterSet',
++            }
++
++    def connectionInitialized(self):
++        self.xmlstream.addObserver(XPATH_ROSTER_GET, self.handleRequest)
++        self.xmlstream.addObserver(XPATH_ROSTER_SET, self.handleRequest)
++
++
++    def _toRosterReply(self, roster, request):
++        response = domish.Element((NS_ROSTER, 'query'))
++
++        for item in roster:
++            response.addChild(item.toElement())
++
++        return response
++
++
++    def _onRosterGet(self, iq):
++        request = Stanza.fromElement(iq)
++
++        d = self.getRoster(request)
++        d.addCallback(self._toRosterReply, request)
++        return d
++
++
++    def getRoster(self, entity):
++        raise NotImplementedError()
-pubsub_client_example.patch
-
-copy_xmppim.patch #+c2s
-jid_cleanup.patch #+c2s
 roster_server.patch #+c2s
 router_unknown.patch #+c2s
 client_listen_authenticator.patch #+c2s
 session_manager.patch #+c2s
 c2s_stanza_handlers.patch #+c2s
 
+version.patch
+
+pubsub_client_example.patch
 pubsub_resource_example.patch
 
 disco_warning.patch #-compatible
 pubsub-item.patch #-compatible
 
+jid_cleanup.patch #+deferred
 pubsub-default-type-attribute.patch #+deferred
 disco_simplify_gatherResults.patch #+deferred
 deprecate_xmpphandler.patch #+deferred
+# HG changeset patch
+# Parent 3cb91cfe0c3dabf07c85d788dcd3e9f5c27ceb4a
+diff --git a/doc/conf.py b/doc/conf.py
+--- a/doc/conf.py
++++ b/doc/conf.py
+@@ -1,7 +1,6 @@
+ # -*- coding: utf-8 -*-
+ #
+-# Wokkel documentation build configuration file, created by
+-# sphinx-quickstart on Mon May  7 11:15:38 2012.
++# Wokkel documentation build configuration file.
+ #
+ # This file is execfile()d with the current directory set to its containing dir.
+ #
+@@ -12,6 +11,7 @@
+ # serve to show the default.
+ 
+ # import sys, os
++from wokkel import __version__
+ 
+ # If extensions (or modules to document with autodoc) are in another directory,
+ # add these directories to sys.path here. If the directory is relative to the
+@@ -48,9 +48,9 @@
+ # built documents.
+ #
+ # The short X.Y version.
+-version = '0.7'
++version = '.'.join(__version__.split('.')[0:2])
+ # The full version, including alpha/beta/rc tags.
+-release = '0.7.0'
++release = __version__
+ 
+ # The language for content autogenerated by Sphinx. Refer to documentation
+ # for a list of supported languages.
+diff --git a/setup.py b/setup.py
+--- a/setup.py
++++ b/setup.py
+@@ -4,6 +4,7 @@
+ # See LICENSE for details.
+ 
+ from setuptools import setup
++from wokkel import __version__
+ 
+ # Make sure 'twisted' doesn't appear in top_level.txt
+ 
+@@ -28,7 +29,7 @@
+     egg_info.write_toplevel_names = _hacked_write_toplevel_names
+ 
+ setup(name='wokkel',
+-      version='0.7.0',
++      version=__version__,
+       description='Twisted Jabber support library',
+       author='Ralph Meijer',
+       author_email='ralphm@ik.nu',
+diff --git a/wokkel/__init__.py b/wokkel/__init__.py
+--- a/wokkel/__init__.py
++++ b/wokkel/__init__.py
+@@ -6,3 +6,5 @@
+ 
+ Support library for Twisted applications using XMPP protocols.
+ """
++
++__version__ = '0.7.0'