Changeset 45:125f9d902a20


Ignore:
Timestamp:
Nov 1, 2008, 7:18:50 PM (13 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@134
Message:

Bring subprotocols code in line with Twisted trunk.

Location:
wokkel
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • wokkel/iwokkel.py

    r43 r45  
    1616    """
    1717
    18     manager = Attribute("""XML stream manager""")
     18    parent = Attribute("""XML stream manager for this handler""")
    1919    xmlstream = Attribute("""The managed XML stream""")
    2020
     
    2626        """
    2727
     28
    2829    def disownHandlerParent(parent):
    2930        """
     
    3233        @type parent: L{IXMPPHandlerCollection}
    3334        """
     35
    3436
    3537    def makeConnection(xs):
     
    4547        @type xs: L{XmlStream<twisted.words.protocols.jabber.XmlStream>}
    4648        """
     49
    4750
    4851    def connectionMade():
     
    5558        """
    5659
     60
    5761    def connectionInitialized():
    5862        """
     
    6468        """
    6569
     70
    6671    def connectionLost(reason):
    6772        """
     
    7580
    7681
     82
    7783class IXMPPHandlerCollection(Interface):
    7884    """
     
    8793        """
    8894
     95
    8996    def addHandler(handler):
    9097        """
     
    94101        """
    95102
     103
    96104    def removeHandler(handler):
    97105        """
     
    100108        @type handler: L{IXMPPHandler}
    101109        """
     110
    102111
    103112
  • wokkel/subprotocols.py

    r22 r45  
    2424
    2525class XMPPHandler(object):
     26    """
     27    XMPP protocol handler.
     28
     29    Classes derived from this class implement (part of) one or more XMPP
     30    extension protocols, and are referred to as a subprotocol implementation.
     31    """
     32
    2633    implements(IXMPPHandler)
     34
     35    def __init__(self):
     36        self.parent = None
     37        self.xmlstream = None
     38
    2739
    2840    def setHandlerParent(self, parent):
     
    3042        self.parent.addHandler(self)
    3143
     44
    3245    def disownHandlerParent(self, parent):
    3346        self.parent.removeHandler(self)
    3447        self.parent = None
    3548
     49
    3650    def makeConnection(self, xs):
    3751        self.xmlstream = xs
    3852        self.connectionMade()
    3953
     54
    4055    def connectionMade(self):
    41         pass
     56        """
     57        Called after a connection has been established.
     58
     59        Can be overridden to perform work before stream initialization.
     60        """
     61
    4262
    4363    def connectionInitialized(self):
    44         pass
     64        """
     65        The XML stream has been initialized.
     66
     67        Can be overridden to perform work after stream initialization, e.g. to
     68        set up observers and start exchanging XML stanzas.
     69        """
     70
    4571
    4672    def connectionLost(self, reason):
     73        """
     74        The XML stream has been closed.
     75
     76        This method can be extended to inspect the C{reason} argument and
     77        act on it.
     78        """
    4779        self.xmlstream = None
     80
    4881
    4982    def send(self, obj):
     
    6598
    6699
     100
    67101class XMPPHandlerCollection(object):
    68102    """
     
    72106    L{XMPPHandler} itself, so this is not recursive.
    73107
    74     @ivar xmlstream: Currently managed XML stream.
    75     @type xmlstream: L{XmlStream}
    76108    @ivar handlers: List of protocol handlers.
    77109    @type handlers: L{list} of objects providing
     
    83115    def __init__(self):
    84116        self.handlers = []
    85         self.xmlstream = None
    86         self._initialized = False
     117
    87118
    88119    def __iter__(self):
     
    92123        return iter(self.handlers)
    93124
     125
    94126    def addHandler(self, handler):
    95127        """
     
    97129
    98130        Protocol handlers are expected to provide L{IXMPPHandler}.
    99 
    100         When an XML stream has already been established, the handler's
    101         C{connectionInitialized} will be called to get it up to speed.
    102         """
    103 
     131        """
    104132        self.handlers.append(handler)
    105133
    106         # get protocol handler up to speed when a connection has already
    107         # been established
    108         if self.xmlstream and self._initialized:
    109             handler.makeConnection(self.xmlstream)
    110             handler.connectionInitialized()
    111134
    112135    def removeHandler(self, handler):
     
    114137        Remove protocol handler.
    115138        """
    116 
    117139        self.handlers.remove(handler)
     140
     141
    118142
    119143class StreamManager(XMPPHandlerCollection):
     
    126150    using L{addHandler}.
    127151
     152    @ivar xmlstream: currently managed XML stream
     153    @type xmlstream: L{XmlStream}
    128154    @ivar logTraffic: if true, log all traffic.
    129155    @type logTraffic: L{bool}
     156    @ivar _initialized: Whether the stream represented by L{xmlstream} has
     157                        been initialized. This is used when caching outgoing
     158                        stanzas.
     159    @type _initialized: C{bool}
    130160    @ivar _packetQueue: internal buffer of unsent data. See L{send} for details.
    131161    @type _packetQueue: L{list}
     
    135165
    136166    def __init__(self, factory):
    137         self.handlers = []
     167        XMPPHandlerCollection.__init__(self)
    138168        self.xmlstream = None
    139169        self._packetQueue = []
     
    147177        self.factory = factory
    148178
     179
     180    def addHandler(self, handler):
     181        """
     182        Add protocol handler.
     183
     184        When an XML stream has already been established, the handler's
     185        C{connectionInitialized} will be called to get it up to speed.
     186        """
     187        XMPPHandlerCollection.addHandler(self, handler)
     188
     189        # get protocol handler up to speed when a connection has already
     190        # been established
     191        if self.xmlstream and self._initialized:
     192            handler.makeConnection(self.xmlstream)
     193            handler.connectionInitialized()
     194
     195
    149196    def _connected(self, xs):
     197        """
     198        Called when the transport connection has been established.
     199
     200        Here we optionally set up traffic logging (depending on L{logTraffic})
     201        and call each handler's C{makeConnection} method with the L{XmlStream}
     202        instance.
     203        """
    150204        def logDataIn(buf):
    151205            log.msg("RECV: %r" % buf)
     
    163217            e.makeConnection(xs)
    164218
     219
    165220    def _authd(self, xs):
     221        """
     222        Called when the stream has been initialized.
     223
     224        Send out cached stanzas and call each handler's
     225        C{connectionInitialized} method.
     226        """
    166227        # Flush all pending packets
    167228        for p in self._packetQueue:
     
    175236            e.connectionInitialized()
    176237
     238
    177239    def initializationFailed(self, reason):
    178240        """
     
    188250        """
    189251
     252
    190253    def _disconnected(self, _):
     254        """
     255        Called when the stream has been closed.
     256
     257        From this point on, the manager doesn't interact with the
     258        L{XmlStream} anymore and notifies each handler that the connection
     259        was lost by calling its C{connectionLost} method.
     260        """
    191261        self.xmlstream = None
    192262        self._initialized = False
     
    195265        # the IService interface
    196266        for e in self:
    197             e.xmlstream = None
    198267            e.connectionLost(None)
     268
    199269
    200270    def send(self, obj):
     
    208278                    L{xmlstream.XmlStream.send} for details.
    209279        """
    210 
    211280        if self._initialized:
    212281            self.xmlstream.send(obj)
    213282        else:
    214283            self._packetQueue.append(obj)
     284
    215285
    216286
  • wokkel/test/test_subprotocols.py

    r4 r45  
    55Tests for L{wokkel.subprotocols}
    66"""
     7
     8from zope.interface.verify import verifyObject
    79
    810from twisted.trial import unittest
     
    1214from twisted.words.protocols.jabber import error, xmlstream
    1315
    14 from wokkel import subprotocols
     16from wokkel import iwokkel, subprotocols
    1517
    1618class DummyFactory(object):
     19    """
     20    Dummy XmlStream factory that only registers bootstrap observers.
     21    """
    1722    def __init__(self):
    1823        self.callbacks = {}
    1924
     25
    2026    def addBootstrap(self, event, callback):
    2127        self.callbacks[event] = callback
    2228
    2329
     30
    2431class DummyXMPPHandler(subprotocols.XMPPHandler):
     32    """
     33    Dummy XMPP subprotocol handler to count the methods are called on it.
     34    """
    2535    def __init__(self):
    2636        self.doneMade = 0
     
    2838        self.doneLost = 0
    2939
     40
    3041    def makeConnection(self, xs):
    3142        self.connectionMade()
    3243
     44
    3345    def connectionMade(self):
    3446        self.doneMade += 1
    3547
     48
    3649    def connectionInitialized(self):
    3750        self.doneInitialized += 1
    3851
     52
    3953    def connectionLost(self, reason):
    4054        self.doneLost += 1
    4155
    4256
     57
    4358class XMPPHandlerTest(unittest.TestCase):
     59    """
     60    Tests for L{subprotocols.XMPPHandler}.
     61    """
     62
     63    def test_interface(self):
     64        """
     65        L{xmlstream.XMPPHandler} implements L{iwokkel.IXMPPHandler}.
     66        """
     67        verifyObject(iwokkel.IXMPPHandler, subprotocols.XMPPHandler())
     68
    4469
    4570    def test_send(self):
     
    4772        Test that data is passed on for sending by the stream manager.
    4873        """
    49 
    5074        class DummyStreamManager(object):
    5175            def __init__(self):
     
    6185
    6286
     87    def test_makeConnection(self):
     88        """
     89        Test that makeConnection saves the XML stream and calls connectionMade.
     90        """
     91        class TestXMPPHandler(subprotocols.XMPPHandler):
     92            def connectionMade(self):
     93                self.doneMade = True
     94
     95        handler = TestXMPPHandler()
     96        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     97        handler.makeConnection(xs)
     98        self.assertTrue(handler.doneMade)
     99        self.assertIdentical(xs, handler.xmlstream)
     100
     101
     102    def test_connectionLost(self):
     103        """
     104        Test that connectionLost forgets the XML stream.
     105        """
     106        handler = subprotocols.XMPPHandler()
     107        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     108        handler.makeConnection(xs)
     109        handler.connectionLost(Exception())
     110        self.assertIdentical(None, handler.xmlstream)
     111
     112
     113
     114class XMPPHandlerCollectionTest(unittest.TestCase):
     115    """
     116    Tests for L{subprotocols.XMPPHandlerCollection}.
     117    """
     118
     119    def setUp(self):
     120        self.collection = subprotocols.XMPPHandlerCollection()
     121
     122
     123    def test_interface(self):
     124        """
     125        L{subprotocols.StreamManager} implements L{iwokkel.IXMPPHandlerCollection}.
     126        """
     127        verifyObject(iwokkel.IXMPPHandlerCollection, self.collection)
     128
     129
     130    def test_addHandler(self):
     131        """
     132        Test the addition of a protocol handler.
     133        """
     134        handler = DummyXMPPHandler()
     135        handler.setHandlerParent(self.collection)
     136        self.assertIn(handler, self.collection)
     137        self.assertIdentical(self.collection, handler.parent)
     138
     139
     140    def test_removeHandler(self):
     141        """
     142        Test removal of a protocol handler.
     143        """
     144        handler = DummyXMPPHandler()
     145        handler.setHandlerParent(self.collection)
     146        handler.disownHandlerParent(self.collection)
     147        self.assertNotIn(handler, self.collection)
     148        self.assertIdentical(None, handler.parent)
     149
     150
     151
    63152class StreamManagerTest(unittest.TestCase):
     153    """
     154    Tests for L{subprotocols.StreamManager}.
     155    """
    64156
    65157    def setUp(self):
     
    83175                          sm.factory.callbacks['//event/xmpp/initfailed'])
    84176
    85     def test__connected(self):
     177
     178    def test_connected(self):
    86179        """
    87180        Test that protocol handlers have their connectionMade method called
     
    97190        self.assertEquals(0, handler.doneLost)
    98191
    99     def test__authd(self):
     192
     193    def test_connectedLogTrafficFalse(self):
     194        """
     195        Test raw data functions unset when logTraffic is set to False.
     196        """
     197        sm = self.streamManager
     198        handler = DummyXMPPHandler()
     199        handler.setHandlerParent(sm)
     200        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     201        sm._connected(xs)
     202        self.assertIdentical(None, xs.rawDataInFn)
     203        self.assertIdentical(None, xs.rawDataOutFn)
     204
     205
     206    def test_connectedLogTrafficTrue(self):
     207        """
     208        Test raw data functions set when logTraffic is set to True.
     209        """
     210        sm = self.streamManager
     211        sm.logTraffic = True
     212        handler = DummyXMPPHandler()
     213        handler.setHandlerParent(sm)
     214        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     215        sm._connected(xs)
     216        self.assertNotIdentical(None, xs.rawDataInFn)
     217        self.assertNotIdentical(None, xs.rawDataOutFn)
     218
     219
     220    def test_authd(self):
    100221        """
    101222        Test that protocol handlers have their connectionInitialized method
     
    111232        self.assertEquals(0, handler.doneLost)
    112233
    113     def test__disconnected(self):
     234
     235    def test_disconnected(self):
    114236        """
    115237        Test that protocol handlers have their connectionLost method
     
    125247        self.assertEquals(1, handler.doneLost)
    126248
     249
    127250    def test_addHandler(self):
    128251        """
     
    132255        handler = DummyXMPPHandler()
    133256        handler.setHandlerParent(sm)
    134         self.assertIn(handler, sm)
    135         self.assertIdentical(sm, handler.parent)
    136257
    137258        self.assertEquals(0, handler.doneMade)
    138259        self.assertEquals(0, handler.doneInitialized)
    139260        self.assertEquals(0, handler.doneLost)
     261
    140262
    141263    def test_addHandlerInitialized(self):
     
    188310        self.assertEquals("<presence/>", xs.transport.value())
    189311
     312
    190313    def test_sendNotConnected(self):
    191314        """
     
    216339
    217340        self.assertEquals("<presence/>", xs.transport.value())
    218         self.failIf(sm._packetQueue)
     341        self.assertFalse(sm._packetQueue)
     342
    219343
    220344    def test_sendNotInitialized(self):
     
    236360        self.assertEquals("<presence/>", sm._packetQueue[0])
    237361
     362
    238363    def test_sendDisconnected(self):
    239364        """
     
    258383
    259384
     385
    260386class DummyIQHandler(subprotocols.IQHandlerMixin):
    261387    iqHandlers = {'/iq[@type="get"]': 'onGet'}
Note: See TracChangeset for help on using the changeset viewer.