source:
ralphm-patches/roster_server.patch
@
72:727b4d29c48e
Last change on this file since 72:727b4d29c48e was 72:727b4d29c48e, checked in by Ralph Meijer <ralphm@…>, 10 years ago | |
---|---|
File size: 7.1 KB |
-
wokkel/test/test_xmppim.py
Add server side support for the roster protocol. * Implements roster get by calling `getRoster` and using the returned `Roster` to send back the roster. TODO: * Add support for roster sets? diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_xmppim.py
a b 1339 1339 1340 1340 1341 1341 1342 class RosterServerProtocolTest(unittest.TestCase, TestableRequestHandlerMixin): 1343 """ 1344 Tests for L{xmppim.RosterServerProtocol}. 1345 """ 1346 1347 def setUp(self): 1348 self.stub = XmlStreamStub() 1349 self.service = xmppim.RosterServerProtocol() 1350 self.service.makeConnection(self.stub.xmlstream) 1351 self.service.connectionInitialized() 1352 1353 1354 def test_onRosterGet(self): 1355 """ 1356 A roster get request should trigger getRoster with the request. 1357 """ 1358 xml = """ 1359 <iq type='get' from='user@example.org' to='user@example.org'> 1360 <query xmlns='jabber:iq:roster'/> 1361 </iq> 1362 """ 1363 1364 def getRoster(request): 1365 self.assertEqual(JID('user@example.org'), request.sender) 1366 item = xmppim.RosterItem(JID('other@example.org'), True, False, 1367 'The User') 1368 roster = xmppim.Roster({item.entity: item}) 1369 return defer.succeed(roster) 1370 1371 def cb(element): 1372 self.assertEquals('query', element.name) 1373 self.assertEquals(NS_ROSTER, element.uri) 1374 itemElements = list(domish.generateElementsQNamed( 1375 element.children, 'item', NS_ROSTER)) 1376 self.assertEqual(1, len(itemElements)) 1377 item = itemElements[0] 1378 self.assertEquals(u'other@example.org', item.getAttribute('jid')) 1379 self.assertEquals(u'to', item.getAttribute('subscription')) 1380 self.assertEquals(u'The User', item.getAttribute('name')) 1381 1382 self.service.getRoster = getRoster 1383 d = self.handleRequest(xml) 1384 d.addCallback(cb) 1385 return d 1386 1387 1388 def test_onRosterGetNotOverridden(self): 1389 """ 1390 If getRoster is not overridden, return feature-not-implemented. 1391 """ 1392 xml = """ 1393 <iq type='get' from='user@example.org' to='user@example.org'> 1394 <query xmlns='jabber:iq:roster'/> 1395 </iq> 1396 """ 1397 1398 d = self.handleRequest(xml) 1399 self.assertFailure(d, NotImplementedError) 1400 return d 1401 1402 1403 def test_onRosterSet(self): 1404 """ 1405 Roster set is not yet supported. 1406 """ 1407 xml = """ 1408 <iq type='set' from='user@example.org' to='user@example.org'> 1409 <query xmlns='jabber:iq:roster'> 1410 <item jid='other@example.org' name='Other User'/> 1411 </query> 1412 </iq> 1413 """ 1414 1415 d = self.handleRequest(xml) 1416 self.assertFailure(d, NotImplementedError) 1417 return d 1418 1419 1420 1342 1421 class MessageTest(unittest.TestCase): 1343 1422 """ 1344 1423 Tests for L{xmppim.Message}. -
wokkel/xmppim.py
diff --git a/wokkel/xmppim.py b/wokkel/xmppim.py
a b 26 26 NS_ROSTER = 'jabber:iq:roster' 27 27 28 28 XPATH_ROSTER_SET = "/iq[@type='set']/query[@xmlns='%s']" % NS_ROSTER 29 XPATH_ROSTER_GET = "/iq[@type='get']/query[@xmlns='%s']" % NS_ROSTER 29 30 30 31 31 32 … … 739 740 740 741 741 742 @classmethod 742 def fromElement( Class, element):743 def fromElement(cls, element): 743 744 entity = JID(element['jid']) 744 item = Class(entity)745 item = cls(entity) 745 746 subscription = element.getAttribute('subscription') 746 747 if subscription == 'remove': 747 748 item.remove = True … … 780 781 version = None 781 782 rosterSet = False 782 783 784 783 785 def parseRequest(self, element): 784 self.version = element.getAttribute('ver')785 786 for child in element.elements(NS_ROSTER, 'item'):787 self.item = RosterItem.fromElement(child)786 roster = Roster.fromElement(element) 787 self.version = roster.version 788 for item in roster.itervalues(): 789 self.item = item 788 790 break 791 return roster 789 792 790 793 791 794 def toElement(self): 792 795 element = Request.toElement(self) 793 query = element.addElement((NS_ROSTER, 'query')) 794 if self.version is not None:795 query['ver']= self.version796 797 roster = Roster() 798 roster.version = self.version 796 799 if self.item: 797 query.addChild(self.item.toElement(rosterSet=self.rosterSet)) 800 roster[self.item.entity] = self.item 801 802 element.addChild(roster.toElement(rosterSet=self.rosterSet)) 803 798 804 return element 799 805 800 806 … … 812 818 813 819 class Roster(dict): 814 820 """ 815 In-memory roster container.821 Roster container. 816 822 817 823 This provides a roster as a mapping from L{JID} to L{RosterItem}. If 818 824 roster versioning is used, the C{version} attribute holds the version … … 825 831 version = None 826 832 827 833 834 @classmethod 835 def fromElement(cls, element): 836 roster = cls() 837 roster.version = element.getAttribute('ver') 838 for element in element.elements(NS_ROSTER, 'item'): 839 item = RosterItem.fromElement(element) 840 roster[item.entity] = item 841 return roster 842 843 844 def toElement(self, rosterSet=False): 845 element = domish.Element((NS_ROSTER, 'query')) 846 847 if self.version: 848 element['ver'] = self.version 849 850 for item in self.itervalues(): 851 element.addChild(item.toElement(rosterSet)) 852 853 return element 854 855 828 856 829 857 class RosterClientProtocol(XMPPHandler, IQHandlerMixin): 830 858 """ … … 898 926 899 927 def processRoster(result): 900 928 if result.query is not None: 901 roster = Roster() 902 roster.version = result.query.getAttribute('ver') 903 for element in result.query.elements(NS_ROSTER, 'item'): 904 item = RosterItem.fromElement(element) 905 roster[item.entity] = item 906 return roster 929 return Roster.fromElement(result.query) 907 930 else: 908 931 return None 909 932 … … 1002 1025 1003 1026 1004 1027 1028 class RosterServerProtocol(XMPPHandler, IQHandlerMixin): 1029 """ 1030 XMPP subprotocol handler for the roster, server side. 1031 """ 1032 1033 iqHandlers = { 1034 XPATH_ROSTER_GET: '_onRosterGet', 1035 # XPATH_ROSTER_SET: '_onRosterSet', 1036 } 1037 1038 def connectionInitialized(self): 1039 self.xmlstream.addObserver(XPATH_ROSTER_GET, self.handleRequest) 1040 self.xmlstream.addObserver(XPATH_ROSTER_SET, self.handleRequest) 1041 1042 1043 def _onRosterGet(self, iq): 1044 request = RosterRequest.fromElement(iq) 1045 1046 def toResponse(roster): 1047 return roster.toElement() 1048 1049 d = self.getRoster(request) 1050 d.addCallback(toResponse) 1051 return d 1052 1053 1054 def getRoster(self, request): 1055 """ 1056 Called when the roster is requested. 1057 1058 @returns: Deferred that fires with a L{Roster}. 1059 @rtype: L{defer.Deferred} 1060 """ 1061 raise NotImplementedError() 1062 1063 1064 1005 1065 class Message(Stanza): 1006 1066 """ 1007 1067 A message stanza.
Note: See TracBrowser
for help on using the repository browser.