mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-24 03:00:15 +00:00
Merge branch 'develop' into roster
This commit is contained in:
commit
c156a4f723
4 changed files with 176 additions and 28 deletions
|
@ -271,24 +271,24 @@ class BaseXMPP(XMLStream):
|
||||||
"""Create a Presence stanza associated with this stream."""
|
"""Create a Presence stanza associated with this stream."""
|
||||||
return Presence(self, *args, **kwargs)
|
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.
|
Create a new Iq stanza with a given Id and from JID.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
id -- An ideally unique ID value for this stanza thread.
|
id -- An ideally unique ID value for this stanza thread.
|
||||||
Defaults to 0.
|
Defaults to 0.
|
||||||
ifrom -- The from JID to use for this stanza.
|
ifrom -- The from JID to use for this stanza.
|
||||||
ito -- The destination JID for this stanza.
|
ito -- The destination JID for this stanza.
|
||||||
type -- The Iq's type, one of: get, set, result, or error.
|
itype -- The Iq's type, one of: get, set, result, or error.
|
||||||
query -- Optional namespace for adding a query element.
|
iquery -- Optional namespace for adding a query element.
|
||||||
"""
|
"""
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
iq['id'] = str(id)
|
iq['id'] = str(id)
|
||||||
iq['to'] = ito
|
iq['to'] = ito
|
||||||
iq['from'] = ifrom
|
iq['from'] = ifrom
|
||||||
iq['type'] = itype
|
iq['type'] = itype
|
||||||
iq['query'] = query
|
iq['query'] = iquery
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
def make_iq_get(self, queryxmlns=None, ito=None, ifrom=None, iq=None):
|
def make_iq_get(self, queryxmlns=None, ito=None, ifrom=None, iq=None):
|
||||||
|
|
|
@ -90,6 +90,10 @@ class xep_0030(base_plugin):
|
||||||
self.description = 'Service Discovery'
|
self.description = 'Service Discovery'
|
||||||
self.stanza = sleekxmpp.plugins.xep_0030.stanza
|
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(
|
self.xmpp.register_handler(
|
||||||
Callback('Disco Info',
|
Callback('Disco Info',
|
||||||
StanzaPath('iq/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
|
by executing the local node handlers, or if a disco#info stanza
|
||||||
must be generated and sent.
|
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:
|
Arguments:
|
||||||
jid -- Request info from this JID.
|
jid -- Request info from this JID.
|
||||||
node -- The particular node to query.
|
node -- The particular node to query.
|
||||||
|
@ -236,7 +243,8 @@ class xep_0030(base_plugin):
|
||||||
ifrom -- Specifiy the sender's JID.
|
ifrom -- Specifiy the sender's JID.
|
||||||
block -- If true, block and wait for the stanzas' reply.
|
block -- If true, block and wait for the stanzas' reply.
|
||||||
timeout -- The time in seconds to block while waiting for
|
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
|
callback -- Optional callback to execute when a reply is
|
||||||
received instead of blocking and waiting for
|
received instead of blocking and waiting for
|
||||||
the reply.
|
the reply.
|
||||||
|
@ -248,7 +256,8 @@ class xep_0030(base_plugin):
|
||||||
return self._fix_default_info(info)
|
return self._fix_default_info(info)
|
||||||
|
|
||||||
iq = self.xmpp.Iq()
|
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['to'] = jid
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq['disco_info']['node'] = node if node else ''
|
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
|
executing the local node handlers, or if a disco#items stanza must
|
||||||
be generated and sent.
|
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:
|
Arguments:
|
||||||
jid -- Request info from this JID.
|
jid -- Request info from this JID.
|
||||||
node -- The particular node to query.
|
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)
|
return self._run_node_handler('get_items', jid, node, kwargs)
|
||||||
|
|
||||||
iq = self.xmpp.Iq()
|
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['to'] = jid
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq['disco_items']['node'] = node if node else ''
|
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)
|
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.
|
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.
|
a node value to reference non-addressable entities.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
jid -- The JID to modify.
|
jid -- The JID for the item.
|
||||||
node -- The node to modify.
|
|
||||||
ijid -- The JID for the item.
|
|
||||||
inode -- Optional node for the item.
|
|
||||||
name -- Optional name 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)
|
self._run_node_handler('add_item', jid, node, kwargs)
|
||||||
|
|
||||||
def del_item(self, jid=None, node=None, **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)
|
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.
|
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.
|
names are different. A category and type is always required.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
jid -- The JID to modify.
|
|
||||||
node -- The node to modify.
|
|
||||||
category -- The identity's category.
|
category -- The identity's category.
|
||||||
itype -- The identity's type.
|
itype -- The identity's type.
|
||||||
name -- Optional name for the identity.
|
name -- Optional name for the identity.
|
||||||
lang -- Optional two-letter language code.
|
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)
|
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.
|
Add a feature to a JID/node combination.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
jid -- The JID to modify.
|
|
||||||
node -- The node to modify.
|
|
||||||
feature -- The namespace of the supported feature.
|
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)
|
self._run_node_handler('add_feature', jid, node, kwargs)
|
||||||
|
|
||||||
def del_identity(self, jid=None, node=None, **kwargs):
|
def del_identity(self, jid=None, node=None, **kwargs):
|
||||||
|
|
127
sleekxmpp/thirdparty/ordereddict.py
vendored
Normal file
127
sleekxmpp/thirdparty/ordereddict.py
vendored
Normal 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
|
|
@ -406,10 +406,10 @@ class TestStreamDisco(SleekTest):
|
||||||
self.xmpp['xep_0030'].make_static(jid='tester@localhost',
|
self.xmpp['xep_0030'].make_static(jid='tester@localhost',
|
||||||
node='testing')
|
node='testing')
|
||||||
|
|
||||||
self.xmpp['xep_0030'].add_item(jid='tester@localhost',
|
self.xmpp['xep_0030'].add_item(ijid='tester@localhost',
|
||||||
node='testing',
|
node='testing',
|
||||||
ijid='tester@localhost',
|
jid='tester@localhost',
|
||||||
inode='foo',
|
subnode='foo',
|
||||||
name='Test')
|
name='Test')
|
||||||
|
|
||||||
self.recv("""
|
self.recv("""
|
||||||
|
@ -446,10 +446,10 @@ class TestStreamDisco(SleekTest):
|
||||||
self.xmpp['xep_0030'].make_static(jid='user@tester.localhost',
|
self.xmpp['xep_0030'].make_static(jid='user@tester.localhost',
|
||||||
node='testing')
|
node='testing')
|
||||||
|
|
||||||
self.xmpp['xep_0030'].add_item(jid='user@tester.localhost',
|
self.xmpp['xep_0030'].add_item(ijid='user@tester.localhost',
|
||||||
node='testing',
|
node='testing',
|
||||||
ijid='user@tester.localhost',
|
jid='user@tester.localhost',
|
||||||
inode='foo',
|
subnode='foo',
|
||||||
name='Test')
|
name='Test')
|
||||||
|
|
||||||
self.recv("""
|
self.recv("""
|
||||||
|
|
Loading…
Reference in a new issue