Changeset 150:2f7237d9c537 for wokkel


Ignore:
Timestamp:
Aug 15, 2011, 9:35:16 AM (9 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
wokkel-muc-client-support-24
Message:

Redo admin requests using generic.Request.

This changes all role and affiliation management functionality to use a
subclass of generic.Request.

The methods for retrieving affiliation or role lists now return lists of
AdminItems, instead of modifying a Room instance and returning that. This
is because affiliation changes can also be done when not in the room.

Location:
wokkel
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • wokkel/iwokkel.py

    r149 r150  
    988988
    989989
    990     def kick(roomJID, entityOrNick, reason=None, sender=None):
     990    def kick(roomJID, nick, reason=None, sender=None):
    991991        """
    992992        Kick a user from a MUC room.
     
    995995        @type roomJID: L{jid.JID}
    996996
    997         @param entityOrNick: The occupant to be banned.
    998         @type entityOrNick: L{jid.JID} or C{unicode}
     997        @param nick: The occupant to be banned.
     998        @type nick: L{jid.JID} or C{unicode}
    999999
    10001000        @param reason: The reason given for the kick.
  • wokkel/muc.py

    r149 r150  
    107107
    108108
    109 class AdminRequest(xmlstream.IQ):
    110     """
    111     A basic admin iq request.
    112 
    113     @ivar method: Type attribute of the IQ request. Either C{'set'} or C{'get'}
    114     @type method: C{str}
    115     """
    116 
    117     def __init__(self, xs, method='get'):
    118         xmlstream.IQ.__init__(self, xs, method)
    119         q = self.addElement((NS_MUC_ADMIN, 'query'))
     109class AdminItem(object):
     110    """
     111    Item representing role and/or affiliation for admin request.
     112    """
     113
     114    def __init__(self, affiliation=None, role=None, entity=None, nick=None,
     115                       reason=None):
     116        self.affiliation = affiliation
     117        self.role = role
     118        self.entity = entity
     119        self.nick = nick
     120        self.reason = reason
     121
     122
     123    def toElement(self):
     124        element = domish.Element((NS_MUC_ADMIN, 'item'))
     125
     126        if self.entity:
     127            element['jid'] = self.entity.full()
     128
     129        if self.nick:
     130            element['nick'] = self.nick
     131
     132        if self.affiliation:
     133            element['affiliation'] = self.affiliation
     134
     135        if self.role:
     136            element['role'] = self.role
     137
     138        if self.reason:
     139            element.addElement('reason', content=self.reason)
     140
     141        return element
     142
     143
     144    @classmethod
     145    def fromElement(Class, element):
     146        item = Class()
     147
     148        if element.hasAttribute('jid'):
     149            item.entity = jid.JID(element['jid'])
     150
     151        item.nick = element.getAttribute('nick')
     152        item.affiliation = element.getAttribute('affiliation')
     153        item.role = element.getAttribute('role')
     154
     155        for child in element.elements(NS_MUC_ADMIN, 'reason'):
     156            item.reason = unicode(child)
     157
     158        return item
     159
     160
     161
     162class AdminStanza(generic.Request):
     163    """
     164    An admin request or response.
     165    """
     166
     167    childParsers = {(NS_MUC_ADMIN, 'query'): '_childParser_query'}
     168
     169    def toElement(self):
     170        element = generic.Request.toElement(self)
     171        element.addElement((NS_MUC_ADMIN, 'query'))
     172
     173        if self.items:
     174            for item in self.items:
     175                element.query.addChild(item.toElement())
     176
     177        return element
     178
     179
     180    def _childParser_query(self, element):
     181        self.items = []
     182        for child in element.elements(NS_MUC_ADMIN, 'item'):
     183            self.items.append(AdminItem.fromElement(child))
    120184
    121185
     
    161225
    162226        return element
    163 
    164 
    165 
    166 class AffiliationRequest(AdminRequest):
    167     """
    168     Register room request.
    169 
    170     @ivar method: Type attribute of the IQ request. Either C{'set'} or C{'get'}
    171     @type method: C{str}
    172 
    173     @ivar affiliation: The affiliation type to send to room.
    174     @type affiliation: C{str}
    175     """
    176 
    177     def __init__(self, xs, method='get', affiliation='none',
    178                        entityOrNick=None, reason=None):
    179         AdminRequest.__init__(self, xs, method)
    180 
    181         self.affiliation = affiliation
    182         self.reason = reason
    183         if entityOrNick:
    184             self.items([entityOrNick])
    185 
    186     def items(self, entities=None):
    187         """
    188         Set or Get the items list for this affiliation request.
    189         """
    190         if entities:
    191             for entityOrNick in entities:
    192                 item = self.query.addElement('item')
    193                 item['affiliation'] = self.affiliation
    194                 try:
    195                     item['jid'] = entityOrNick.full()
    196                 except AttributeError:
    197                     item['nick'] = entityOrNick
    198 
    199                 if self.reason:
    200                     item.addElement('reason', content=self.reason)
    201 
    202         return self.query.elements()
    203 
    204 
    205 
    206 class RoleRequest(AdminRequest):
    207     def __init__(self, xs, method='get', role='none',
    208                        entityOrNick=None, reason=None):
    209         AdminRequest.__init__(self, xs, method)
    210 
    211         item = self.query.addElement('item')
    212         item['role'] = role
    213         try:
    214             item['jid'] = entityOrNick.full()
    215         except AttributeError:
    216             item['nick'] = entityOrNick
    217 
    218         if reason:
    219             item.addElement('reason', content=self.reason)
    220227
    221228
     
    10991106        Send a request for an affiliation list in a room.
    11001107        """
    1101         iq = AffiliationRequest(self.xmlstream,
    1102                                 method='get',
    1103                                 affiliation=affiliation,
    1104                                 )
    1105         iq['to'] = roomJID.userhost()
    1106         return iq.send()
     1108        def cb(response):
     1109            stanza = AdminStanza.fromElement(response)
     1110            return stanza.items
     1111
     1112        request = AdminStanza(recipient=roomJID, stanzaType='get')
     1113        request.items = [AdminItem(affiliation=affiliation)]
     1114        d = self.request(request)
     1115        d.addCallback(cb)
     1116        return d
    11071117
    11081118
    11091119    def _getRoleList(self, roomJID, role):
    11101120        """
    1111         Send a role request.
    1112         """
    1113         iq = RoleRequest(self.xmlstream,
    1114                          method='get',
    1115                          role=role,
    1116                          )
    1117         iq['to'] = roomJID.full()
    1118         return iq.send()
    1119 
    1120 
    1121     def _setAffiliationList(self, iq, affiliation, occupantJID):
    1122         # set a rooms affiliation list
    1123         room = self._getRoom(occupantJID)
    1124         if room is not None:
    1125             affiliation_list = []
    1126             setattr(room, affiliation, [])
    1127 
    1128             for item in iq.query.elements():
    1129                 nick = item.getAttribute('nick', None)
    1130                 entity = item.getAttribute('jid', None)
    1131                 role = item.getAttribute('role', None)
    1132                 user = None
    1133                 if nick is None and entity is None:
    1134                     raise Exception, 'bad attributes in item list'
    1135                 if nick is not None:
    1136                     user = room.getUser(nick)
    1137                 if user is None:
    1138                     user = User(nick, entity=jid.internJID(entity))
    1139                     user.affiliation = 'member'
    1140                 if role is not None:
    1141                     user.role = role
    1142 
    1143                 affiliation_list.append(user)
    1144 
    1145             setattr(room, affiliation, affiliation_list)
    1146         return room
     1121        Send a request for a role list in a room.
     1122        """
     1123        def cb(response):
     1124            stanza = AdminStanza.fromElement(response)
     1125            return stanza.items
     1126
     1127        request = AdminStanza(recipient=roomJID, stanzaType='get')
     1128        request.items = [AdminItem(role=role)]
     1129        d = self.request(request)
     1130        d.addCallback(cb)
     1131        return d
    11471132
    11481133
     
    11541139        @type roomJID: L{jid.JID}
    11551140        """
    1156         d = self._getAffiliationList(roomJID, 'member')
    1157         d.addCallback(self._setAffiliationList, 'members', roomJID)
    1158         return d
     1141        return self._getAffiliationList(roomJID, 'member')
    11591142
    11601143
     
    11661149        @type roomJID: L{jid.JID}
    11671150        """
    1168         d = self._getAffiliationList(roomJID, 'admin')
    1169         d.addCallback(self._setAffiliationList, 'admin', roomJID)
    1170         return d
     1151        return self._getAffiliationList(roomJID, 'admin')
    11711152
    11721153
     
    11781159        @type roomJID: L{jid.JID}
    11791160        """
    1180         d = self._getAffiliationList(roomJID, 'outcast')
    1181         d.addCallback(self._setAffiliationList, 'outcast', roomJID)
    1182         return d
     1161        return self._getAffiliationList(roomJID, 'outcast')
    11831162
    11841163
     
    11871166        Get an owner list from a room.
    11881167
    1189         @param roomJID: The room jabber/xmpp entity id for the requested member
    1190             list.
    1191         @type roomJID: L{jid.JID}
    1192         """
    1193         d = self._getAffiliationList(roomJID, 'owner')
    1194         d.addCallback(self._setAffiliationList, 'owner', roomJID)
     1168        @param roomJID: The bare JID of the room.
     1169        @type roomJID: L{jid.JID}
     1170        """
     1171        return self._getAffiliationList(roomJID, 'owner')
     1172
     1173
     1174    def getModeratorList(self, roomJID):
     1175        """
     1176        Get the moderator list of a room.
     1177
     1178        @param roomJID: The bare JID of the room.
     1179        @type roomJID: L{jid.JID}
     1180        """
     1181        d = self._getRoleList(roomJID, 'moderator')
    11951182        return d
    11961183
     
    12971284
    12981285
    1299     def _setAffiliation(self, roomJID, entityOrNick, affiliation,
     1286    def _setAffiliation(self, roomJID, entity, affiliation,
    13001287                              reason=None, sender=None):
    13011288        """
    13021289        Send a request to change an entity's affiliation to a MUC room.
    13031290        """
    1304         iq = AffiliationRequest(self.xmlstream,
    1305                                 method='set',
    1306                                 entityOrNick=entityOrNick,
    1307                                 affiliation=affiliation,
    1308                                 reason=reason)
    1309         iq['to'] = roomJID.userhost()
    1310         if sender is not None:
    1311             iq['from'] = unicode(sender)
    1312 
    1313         return iq.send()
    1314 
    1315 
    1316     def _setRole(self, roomJID, entityOrNick, role,
     1291        request = AdminStanza(recipient=roomJID, sender=sender,
     1292                               stanzaType='set')
     1293        item = AdminItem(entity=entity, affiliation=affiliation, reason=reason)
     1294        request.items = [item]
     1295        return self.request(request)
     1296
     1297
     1298    def _setRole(self, roomJID, nick, role,
    13171299                       reason=None, sender=None):
    1318         # send a role request
    1319         iq = RoleRequest(self.xmlstream,
    1320                          method='set',
    1321                          role=role,
    1322                          entityOrNick=entityOrNick,
    1323                          reason=reason)
    1324 
    1325         iq['to'] = roomJID.userhost()
    1326         if sender is not None:
    1327             iq['from'] = unicode(sender)
    1328         return iq.send()
    1329 
    1330 
    1331     def modifyAffiliationList(self, frm, roomJID, jid_list, affiliation):
     1300        """
     1301        Send a request to change an occupant's role in a MUC room.
     1302        """
     1303        request = AdminStanza(recipient=roomJID, sender=sender,
     1304                               stanzaType='set')
     1305        item = AdminItem(nick=nick, role=role, reason=reason)
     1306        request.items = [item]
     1307        return self.request(request)
     1308
     1309
     1310    def modifyAffiliationList(self, roomJID, entities, affiliation,
     1311                                    sender=None):
    13321312        """
    13331313        Modify an affiliation list.
    13341314
    1335         @param frm: The entity sending the request.
    1336         @type frm: L{jid.JID}
    1337 
    1338         @param roomJID: The bare JID of the room.
    1339         @type roomJID: L{jid.JID}
    1340 
    1341         @param entities: The list of entities to change in a room. This can be
    1342             a nick or a full jid.
    1343         @type jid_list: L{list} of C{unicode} for nicks. L{list} of L{jid.JID}
    1344             for jids.
    1345 
    1346         @param affiliation: The affilation to change.
     1315        @param roomJID: The bare JID of the room.
     1316        @type roomJID: L{jid.JID}
     1317
     1318        @param entities: The list of entities to change for a room.
     1319        @type entities: L{list} of L{jid.JID}
     1320
     1321        @param affiliation: The affilation to the entities will acquire.
    13471322        @type affiliation: C{unicode}
    13481323
    1349         """
    1350         iq = AffiliationRequest(self.xmlstream,
    1351                                 method='set',
    1352                                 affiliation=affiliation,
    1353                                 )
    1354         iq.items(jid_list)
    1355         iq['to'] = roomJID.userhost()
    1356         iq['from'] = frm.full()
    1357         return iq.send()
     1324        @param sender: The entity sending the request.
     1325        @type sender: L{jid.JID}
     1326
     1327        """
     1328        request = AdminStanza(recipient=roomJID, sender=sender,
     1329                               stanzaType='set')
     1330        request.items = [AdminItem(entity=entity, affiliation=affiliation)
     1331                         for entity in entities]
     1332
     1333        return self.request(request)
    13581334
    13591335
     
    13741350        @type sender: L{jid.JID}
    13751351        """
    1376         return self._setRole(roomJID, entityOrNick=nick,
     1352        return self._setRole(roomJID, nick=nick,
    13771353                             role='participant',
    13781354                             reason=reason, sender=sender)
     
    13971373        @type sender: L{jid.JID}
    13981374        """
    1399         return self._setRole(roomJID, entityOrNick=nick, role='visitor',
     1375        return self._setRole(roomJID, nick=nick, role='visitor',
    14001376                             reason=reason, sender=sender)
    14011377
     
    14171393        @type sender: L{jid.JID}
    14181394        """
    1419         return self._setRole(roomJID, entityOrNick=nick, role='moderator',
     1395        return self._setRole(roomJID, nick=nick, role='moderator',
    14201396                             reason=reason, sender=sender)
    14211397
     
    14411417
    14421418
    1443     def kick(self, roomJID, entityOrNick, reason=None, sender=None):
     1419    def kick(self, roomJID, nick, reason=None, sender=None):
    14441420        """
    14451421        Kick a user from a MUC room.
     
    14481424        @type roomJID: L{jid.JID}
    14491425
    1450         @param entityOrNick: The occupant to be banned.
    1451         @type entityOrNick: L{jid.JID} or C{unicode}
     1426        @param nick: The occupant to be banned.
     1427        @type nick: C{unicode}
    14521428
    14531429        @param reason: The reason given for the kick.
     
    14571433        @type sender: L{jid.JID}
    14581434        """
    1459         return self._setAffiliation(roomJID, entityOrNick, 'none',
    1460                                     reason=reason, sender=sender)
     1435        return self._setRole(roomJID, nick, 'none',
     1436                             reason=reason, sender=sender)
  • wokkel/test/test_muc.py

    r148 r150  
    378378            self.assertTrue(banned, 'Did not ban user')
    379379
    380         d = self.protocol.ban(self.occupantJID, banned, reason='Spam',
     380        d = self.protocol.ban(self.roomJID, banned, reason='Spam',
    381381                              sender=self.userJID)
    382382        d.addCallback(cb)
     
    405405            self.assertTrue(kicked, 'Did not kick user')
    406406
    407         d = self.protocol.kick(self.occupantJID, nick, reason='Spam',
     407        d = self.protocol.kick(self.roomJID, nick, reason='Spam',
    408408                               sender=self.userJID)
    409409        d.addCallback(cb)
     
    413413        self.assertTrue(xpath.matches(
    414414                u"/iq[@type='set' and @to='%s']/query/item"
    415                     "[@affiliation='none']" % (self.roomJID,),
     415                    "[@role='none']" % (self.roomJID,),
    416416                iq),
    417417            'Wrong kick stanza')
     
    800800
    801801
     802    def test_modifyAffiliationList(self):
     803
     804        entities = [JID('user1@test.example.org'),
     805                    JID('user2@test.example.org')]
     806        d = self.protocol.modifyAffiliationList(self.roomJID, entities,
     807                                                'admin')
     808
     809        iq = self.stub.output[-1]
     810        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     811                                                              muc.NS_MUC_ADMIN)
     812        items = xpath.queryForNodes(query, iq)
     813        self.assertNotIdentical(None, items)
     814        self.assertEquals(entities[0], JID(items[0].getAttribute('jid')))
     815        self.assertEquals('admin', items[0].getAttribute('affiliation'))
     816        self.assertEquals(entities[1], JID(items[1].getAttribute('jid')))
     817        self.assertEquals('admin', items[1].getAttribute('affiliation'))
     818
     819        # Send a response to have the deferred fire.
     820        response = toResponse(iq, 'result')
     821        self.stub.send(response)
     822        return d
     823
     824
    802825    def test_grantVoice(self):
    803826        """
    804         Test granting voice to a user.
    805 
     827        Granting voice sends request to set role to 'participant'.
    806828        """
    807829        nick = 'TroubleMaker'
     
    809831            self.assertTrue(give_voice, 'Did not give voice user')
    810832
    811         d = self.protocol.grantVoice(self.occupantJID, nick,
     833        d = self.protocol.grantVoice(self.roomJID, nick,
    812834                                     sender=self.userJID)
    813835        d.addCallback(cb)
     
    817839        query = (u"/iq[@type='set' and @to='%s']/query/item"
    818840                     "[@role='participant']") % self.roomJID
     841        self.assertTrue(xpath.matches(query, iq), 'Wrong voice stanza')
     842
     843        response = toResponse(iq, 'result')
     844        self.stub.send(response)
     845        return d
     846
     847
     848    def test_revokeVoice(self):
     849        """
     850        Revoking voice sends request to set role to 'visitor'.
     851        """
     852        nick = 'TroubleMaker'
     853
     854        d = self.protocol.revokeVoice(self.roomJID, nick,
     855                                      reason="Trouble maker",
     856                                      sender=self.userJID)
     857
     858        iq = self.stub.output[-1]
     859
     860        query = (u"/iq[@type='set' and @to='%s']/query/item"
     861                     "[@role='visitor']") % self.roomJID
     862        self.assertTrue(xpath.matches(query, iq), 'Wrong voice stanza')
     863
     864        response = toResponse(iq, 'result')
     865        self.stub.send(response)
     866        return d
     867
     868
     869    def test_grantModerator(self):
     870        """
     871        Granting moderator privileges sends request to set role to 'moderator'.
     872        """
     873        nick = 'TroubleMaker'
     874
     875        d = self.protocol.grantModerator(self.roomJID, nick,
     876                                         sender=self.userJID)
     877
     878        iq = self.stub.output[-1]
     879
     880        query = (u"/iq[@type='set' and @to='%s']/query/item"
     881                     "[@role='moderator']") % self.roomJID
    819882        self.assertTrue(xpath.matches(query, iq), 'Wrong voice stanza')
    820883
     
    863926
    864927    def test_getMemberList(self):
    865         def cb(room):
    866             members = room.members
    867             self.assertEquals(1, len(members))
    868             user = members[0]
    869             self.assertEquals(JID(u'hag66@shakespeare.lit'), user.entity)
    870             self.assertEquals(u'thirdwitch', user.nick)
    871             self.assertEquals(u'participant', user.role)
    872 
    873         self._createRoom()
     928        """
     929        Retrieving the member list returns a list of L{muc.AdminItem}s
     930
     931        The request asks for the affiliation C{'member'}.
     932        """
     933        def cb(items):
     934            self.assertEquals(1, len(items))
     935            item = items[0]
     936            self.assertEquals(JID(u'hag66@shakespeare.lit'), item.entity)
     937            self.assertEquals(u'thirdwitch', item.nick)
     938            self.assertEquals(u'member', item.affiliation)
     939
    874940        d = self.protocol.getMemberList(self.roomJID)
    875941        d.addCallback(cb)
    876942
    877943        iq = self.stub.output[-1]
    878         query = iq.query
    879         self.assertNotIdentical(None, query)
    880         self.assertEquals(NS_MUC_ADMIN, query.uri)
     944        self.assertEquals('get', iq.getAttribute('type'))
     945        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     946                                                              muc.NS_MUC_ADMIN)
     947        items = xpath.queryForNodes(query, iq)
     948        self.assertNotIdentical(None, items)
     949        self.assertEquals(1, len(items))
     950        self.assertEquals('member', items[0].getAttribute('affiliation'))
    881951
    882952        response = toResponse(iq, 'result')
     
    890960
    891961        return d
     962
     963
     964    def test_getAdminList(self):
     965        """
     966        Retrieving the admin list returns a list of L{muc.AdminItem}s
     967
     968        The request asks for the affiliation C{'admin'}.
     969        """
     970        d = self.protocol.getAdminList(self.roomJID)
     971
     972        iq = self.stub.output[-1]
     973        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     974                                                              muc.NS_MUC_ADMIN)
     975        items = xpath.queryForNodes(query, iq)
     976        self.assertEquals('admin', items[0].getAttribute('affiliation'))
     977
     978        response = toResponse(iq, 'result')
     979        query = response.addElement((NS_MUC_ADMIN, 'query'))
     980        self.stub.send(response)
     981
     982        return d
     983
     984
     985    def test_getBanList(self):
     986        """
     987        Retrieving the ban list returns a list of L{muc.AdminItem}s
     988
     989        The request asks for the affiliation C{'outcast'}.
     990        """
     991        def cb(items):
     992            self.assertEquals(1, len(items))
     993            item = items[0]
     994            self.assertEquals(JID(u'hag66@shakespeare.lit'), item.entity)
     995            self.assertEquals(u'outcast', item.affiliation)
     996            self.assertEquals(u'Trouble making', item.reason)
     997
     998        d = self.protocol.getBanList(self.roomJID)
     999        d.addCallback(cb)
     1000
     1001        iq = self.stub.output[-1]
     1002        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     1003                                                              muc.NS_MUC_ADMIN)
     1004        items = xpath.queryForNodes(query, iq)
     1005        self.assertEquals('outcast', items[0].getAttribute('affiliation'))
     1006
     1007        response = toResponse(iq, 'result')
     1008        query = response.addElement((NS_MUC_ADMIN, 'query'))
     1009        item = query.addElement('item')
     1010        item['affiliation'] ='outcast'
     1011        item['jid'] = 'hag66@shakespeare.lit'
     1012        item.addElement('reason', content='Trouble making')
     1013        self.stub.send(response)
     1014
     1015        return d
     1016
     1017
     1018    def test_getOwnerList(self):
     1019        """
     1020        Retrieving the owner list returns a list of L{muc.AdminItem}s
     1021
     1022        The request asks for the affiliation C{'owner'}.
     1023        """
     1024        d = self.protocol.getOwnerList(self.roomJID)
     1025
     1026        iq = self.stub.output[-1]
     1027        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     1028                                                              muc.NS_MUC_ADMIN)
     1029        items = xpath.queryForNodes(query, iq)
     1030        self.assertEquals('owner', items[0].getAttribute('affiliation'))
     1031
     1032        response = toResponse(iq, 'result')
     1033        query = response.addElement((NS_MUC_ADMIN, 'query'))
     1034        self.stub.send(response)
     1035
     1036        return d
     1037
     1038
     1039    def test_getModeratorList(self):
     1040        """
     1041        Retrieving the moderator returns a list of L{muc.AdminItem}s.
     1042
     1043        The request asks for the role C{'moderator'}.
     1044        """
     1045
     1046        def cb(items):
     1047            self.assertEquals(1, len(items))
     1048            item = items[0]
     1049            self.assertEquals(JID(u'hag66@shakespeare.lit'), item.entity)
     1050            self.assertEquals(u'thirdwitch', item.nick)
     1051            self.assertEquals(u'moderator', item.role)
     1052
     1053        d = self.protocol.getModeratorList(self.roomJID)
     1054        d.addCallback(cb)
     1055
     1056        iq = self.stub.output[-1]
     1057        self.assertEquals('get', iq.getAttribute('type'))
     1058        query = "/iq/query[@xmlns='%s']/item[@xmlns='%s']" % (muc.NS_MUC_ADMIN,
     1059                                                              muc.NS_MUC_ADMIN)
     1060        items = xpath.queryForNodes(query, iq)
     1061        self.assertNotIdentical(None, items)
     1062        self.assertEquals(1, len(items))
     1063        self.assertEquals('moderator', items[0].getAttribute('role'))
     1064
     1065        response = toResponse(iq, 'result')
     1066        query = response.addElement((NS_MUC_ADMIN, 'query'))
     1067        item = query.addElement('item')
     1068        item['affiliation'] ='member'
     1069        item['jid'] = 'hag66@shakespeare.lit'
     1070        item['nick'] = 'thirdwitch'
     1071        item['role'] = 'moderator'
     1072        self.stub.send(response)
     1073
     1074        return d
Note: See TracChangeset for help on using the changeset viewer.