mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-23 19:19:53 +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."""
|
||||
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.
|
||||
|
||||
Arguments:
|
||||
id -- An ideally unique ID value for this stanza thread.
|
||||
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.
|
||||
id -- An ideally unique ID value for this stanza thread.
|
||||
Defaults to 0.
|
||||
ifrom -- The from JID to use for this stanza.
|
||||
ito -- The destination JID for this stanza.
|
||||
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):
|
||||
|
|
|
@ -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
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',
|
||||
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("""
|
||||
|
|
Loading…
Reference in a new issue