Merge branch 'develop' into roster

This commit is contained in:
Lance Stout 2011-01-05 16:53:33 -05:00
commit c156a4f723
4 changed files with 176 additions and 28 deletions

View file

@ -271,7 +271,7 @@ class BaseXMPP(XMLStream):
"""Create a Presence stanza associated with this stream."""
return Presence(self, *args, **kwargs)
def make_iq(self, id=0, ifrom=None, ito=None, type=None, query=None):
def make_iq(self, id=0, ifrom=None, ito=None, itype=None, iquery=None):
"""
Create a new Iq stanza with a given Id and from JID.
@ -280,15 +280,15 @@ class BaseXMPP(XMLStream):
Defaults to 0.
ifrom -- The from JID to use for this stanza.
ito -- The destination JID for this stanza.
type -- The Iq's type, one of: get, set, result, or error.
query -- Optional namespace for adding a query element.
itype -- The Iq's type, one of: get, set, result, or error.
iquery -- Optional namespace for adding a query element.
"""
iq = self.Iq()
iq['id'] = str(id)
iq['to'] = ito
iq['from'] = ifrom
iq['type'] = itype
iq['query'] = query
iq['query'] = iquery
return iq
def make_iq_get(self, queryxmlns=None, ito=None, ifrom=None, iq=None):

View file

@ -90,6 +90,10 @@ class xep_0030(base_plugin):
self.description = 'Service Discovery'
self.stanza = sleekxmpp.plugins.xep_0030.stanza
# Retain some backwards compatibility
self.getInfo = self.get_info
self.getItems = self.get_items
self.xmpp.register_handler(
Callback('Disco Info',
StanzaPath('iq/disco_info'),
@ -225,6 +229,9 @@ class xep_0030(base_plugin):
by executing the local node handlers, or if a disco#info stanza
must be generated and sent.
If requesting items from a local JID/node, then only a DiscoInfo
stanza will be returned. Otherwise, an Iq stanza will be returned.
Arguments:
jid -- Request info from this JID.
node -- The particular node to query.
@ -236,7 +243,8 @@ class xep_0030(base_plugin):
ifrom -- Specifiy the sender's JID.
block -- If true, block and wait for the stanzas' reply.
timeout -- The time in seconds to block while waiting for
a reply. If None, then wait indefinitely.
a reply. If None, then wait indefinitely. The
timeout value is only used when block=True.
callback -- Optional callback to execute when a reply is
received instead of blocking and waiting for
the reply.
@ -248,7 +256,8 @@ class xep_0030(base_plugin):
return self._fix_default_info(info)
iq = self.xmpp.Iq()
iq['from'] = kwargs.get('ifrom', '')
# Check dfrom parameter for backwards compatibility
iq['from'] = kwargs.get('ifrom', kwargs.get('dfrom', ''))
iq['to'] = jid
iq['type'] = 'get'
iq['disco_info']['node'] = node if node else ''
@ -265,6 +274,9 @@ class xep_0030(base_plugin):
executing the local node handlers, or if a disco#items stanza must
be generated and sent.
If requesting items from a local JID/node, then only a DiscoItems
stanza will be returned. Otherwise, an Iq stanza will be returned.
Arguments:
jid -- Request info from this JID.
node -- The particular node to query.
@ -285,7 +297,8 @@ class xep_0030(base_plugin):
return self._run_node_handler('get_items', jid, node, kwargs)
iq = self.xmpp.Iq()
iq['from'] = kwargs.get('ifrom', '')
# Check dfrom parameter for backwards compatibility
iq['from'] = kwargs.get('ifrom', kwargs.get('dfrom', ''))
iq['to'] = jid
iq['type'] = 'get'
iq['disco_items']['node'] = node if node else ''
@ -317,7 +330,7 @@ class xep_0030(base_plugin):
"""
self._run_node_handler('del_items', jid, node, kwargs)
def add_item(self, jid=None, node=None, **kwargs):
def add_item(self, jid=None, name='', node=None, subnode='', ijid=None):
"""
Add a new item element to the given JID/node combination.
@ -325,12 +338,15 @@ class xep_0030(base_plugin):
a node value to reference non-addressable entities.
Arguments:
jid -- The JID to modify.
node -- The node to modify.
ijid -- The JID for the item.
inode -- Optional node for the item.
jid -- The JID for the item.
name -- Optional name for the item.
node -- The node to modify.
subnode -- Optional node for the item.
ijid -- The JID to modify.
"""
kwargs = {'ijid': jid,
'name': name,
'inode': subnode}
self._run_node_handler('add_item', jid, node, kwargs)
def del_item(self, jid=None, node=None, **kwargs):
@ -345,7 +361,7 @@ class xep_0030(base_plugin):
"""
self._run_node_handler('del_item', jid, node, kwargs)
def add_identity(self, jid=None, node=None, **kwargs):
def add_identity(self, category='', itype='', name='', node=None, jid=None, lang=None):
"""
Add a new identity to the given JID/node combination.
@ -358,24 +374,29 @@ class xep_0030(base_plugin):
names are different. A category and type is always required.
Arguments:
jid -- The JID to modify.
node -- The node to modify.
category -- The identity's category.
itype -- The identity's type.
name -- Optional name for the identity.
lang -- Optional two-letter language code.
node -- The node to modify.
jid -- The JID to modify.
"""
kwargs = {'category': category,
'itype': itype,
'name': name,
'lang': lang}
self._run_node_handler('add_identity', jid, node, kwargs)
def add_feature(self, jid=None, node=None, **kwargs):
def add_feature(self, feature, node=None, jid=None):
"""
Add a feature to a JID/node combination.
Arguments:
jid -- The JID to modify.
node -- The node to modify.
feature -- The namespace of the supported feature.
node -- The node to modify.
jid -- The JID to modify.
"""
kwargs = {'feature': feature}
self._run_node_handler('add_feature', jid, node, kwargs)
def del_identity(self, jid=None, node=None, **kwargs):

127
sleekxmpp/thirdparty/ordereddict.py vendored Normal file
View file

@ -0,0 +1,127 @@
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
from UserDict import DictMixin
class OrderedDict(dict, DictMixin):
def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)
def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)
def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)
def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev
def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]
def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]
def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
if last:
key = reversed(self).next()
else:
key = iter(self).next()
value = self.pop(key)
return key, value
def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)
def keys(self):
return list(self)
setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())
def copy(self):
return self.__class__(self)
@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d
def __eq__(self, other):
if isinstance(other, OrderedDict):
if len(self) != len(other):
return False
for p, q in zip(self.items(), other.items()):
if p != q:
return False
return True
return dict.__eq__(self, other)
def __ne__(self, other):
return not self == other

View file

@ -406,10 +406,10 @@ class TestStreamDisco(SleekTest):
self.xmpp['xep_0030'].make_static(jid='tester@localhost',
node='testing')
self.xmpp['xep_0030'].add_item(jid='tester@localhost',
self.xmpp['xep_0030'].add_item(ijid='tester@localhost',
node='testing',
ijid='tester@localhost',
inode='foo',
jid='tester@localhost',
subnode='foo',
name='Test')
self.recv("""
@ -446,10 +446,10 @@ class TestStreamDisco(SleekTest):
self.xmpp['xep_0030'].make_static(jid='user@tester.localhost',
node='testing')
self.xmpp['xep_0030'].add_item(jid='user@tester.localhost',
self.xmpp['xep_0030'].add_item(ijid='user@tester.localhost',
node='testing',
ijid='user@tester.localhost',
inode='foo',
jid='user@tester.localhost',
subnode='foo',
name='Test')
self.recv("""