Compare commits
11 Commits
slix-1.2
...
slix-1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36824379c3 | ||
|
|
a0a37c19ff | ||
|
|
1b5fe57a5e | ||
|
|
5da31db0c7 | ||
|
|
f8cea760b6 | ||
|
|
5ef01ecdd1 | ||
|
|
62aafe0ee7 | ||
|
|
cf3f36ac52 | ||
|
|
b88d2ecd77 | ||
|
|
e691850a2b | ||
|
|
d4bff8dee6 |
@@ -79,7 +79,7 @@ def _validate_node(node):
|
||||
:returns: The local portion of a JID, as validated by nodeprep.
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
return ''
|
||||
|
||||
try:
|
||||
node = nodeprep(node)
|
||||
@@ -160,7 +160,7 @@ def _validate_resource(resource):
|
||||
:returns: The local portion of a JID, as validated by resourceprep.
|
||||
"""
|
||||
if resource is None:
|
||||
return None
|
||||
return ''
|
||||
|
||||
try:
|
||||
resource = resourceprep(resource)
|
||||
|
||||
@@ -23,13 +23,13 @@ class GmailQuery(ElementBase):
|
||||
plugin_attrib = 'gmail'
|
||||
interfaces = set(('newer-than-time', 'newer-than-tid', 'q', 'search'))
|
||||
|
||||
def getSearch(self):
|
||||
def get_search(self):
|
||||
return self['q']
|
||||
|
||||
def setSearch(self, search):
|
||||
def set_search(self, search):
|
||||
self['q'] = search
|
||||
|
||||
def delSearch(self):
|
||||
def del_search(self):
|
||||
del self['q']
|
||||
|
||||
|
||||
@@ -40,17 +40,17 @@ class MailBox(ElementBase):
|
||||
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
||||
'url', 'threads', 'matched', 'estimate'))
|
||||
|
||||
def getThreads(self):
|
||||
def get_threads(self):
|
||||
threads = []
|
||||
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
||||
MailThread.name)):
|
||||
threads.append(MailThread(xml=threadXML, parent=None))
|
||||
return threads
|
||||
|
||||
def getMatched(self):
|
||||
def get_matched(self):
|
||||
return self['total-matched']
|
||||
|
||||
def getEstimate(self):
|
||||
def get_estimate(self):
|
||||
return self['total-estimate'] == '1'
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class MailThread(ElementBase):
|
||||
'senders', 'url', 'labels', 'subject', 'snippet'))
|
||||
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
||||
|
||||
def getSenders(self):
|
||||
def get_senders(self):
|
||||
senders = []
|
||||
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
||||
if sendersXML is not None:
|
||||
@@ -77,10 +77,10 @@ class MailSender(ElementBase):
|
||||
plugin_attrib = 'sender'
|
||||
interfaces = set(('address', 'name', 'originator', 'unread'))
|
||||
|
||||
def getOriginator(self):
|
||||
def get_originator(self):
|
||||
return self.xml.attrib.get('originator', '0') == '1'
|
||||
|
||||
def getUnread(self):
|
||||
def get_unread(self):
|
||||
return self.xml.attrib.get('unread', '0') == '1'
|
||||
|
||||
|
||||
|
||||
@@ -92,13 +92,13 @@ def _py2xml(*args):
|
||||
def xml2py(params):
|
||||
namespace = 'jabber:iq:rpc'
|
||||
vals = []
|
||||
for param in params.xml.findall('{%s}param' % namespace):
|
||||
for param in params.findall('{%s}param' % namespace):
|
||||
vals.append(_xml2py(param.find('{%s}value' % namespace)))
|
||||
return vals
|
||||
|
||||
def _xml2py(value):
|
||||
namespace = 'jabber:iq:rpc'
|
||||
find_value = value.xml.find
|
||||
find_value = value.find
|
||||
if find_value('{%s}nil' % namespace) is not None:
|
||||
return None
|
||||
if find_value('{%s}i4' % namespace) is not None:
|
||||
|
||||
@@ -117,9 +117,12 @@ for atype in ('all', 'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'):
|
||||
setattr(Addresses, "set_%s" % atype, set_multi)
|
||||
setattr(Addresses, "del_%s" % atype, del_multi)
|
||||
|
||||
# To retain backwards compatibility:
|
||||
if atype == 'all':
|
||||
Addresses.interfaces.add('addresses')
|
||||
setattr(Addresses, "get_addresses", get_multi)
|
||||
setattr(Addresses, "set_addresses", set_multi)
|
||||
setattr(Addresses, "del_addresses", del_multi)
|
||||
|
||||
|
||||
|
||||
register_stanza_plugin(Addresses, Address, iterable=True)
|
||||
|
||||
@@ -206,7 +206,10 @@ class Options(ElementBase):
|
||||
return form
|
||||
|
||||
def set_options(self, value):
|
||||
self.xml.append(value)
|
||||
if isinstance(value, ElementBase):
|
||||
self.xml.append(value.xml)
|
||||
else:
|
||||
self.xml.append(value)
|
||||
return self
|
||||
|
||||
def del_options(self):
|
||||
@@ -238,7 +241,10 @@ class PublishOptions(ElementBase):
|
||||
if value is None:
|
||||
self.del_publish_options()
|
||||
else:
|
||||
self.xml.append(value)
|
||||
if isinstance(value, ElementBase):
|
||||
self.xml.append(value.xml)
|
||||
else:
|
||||
self.xml.append(value)
|
||||
return self
|
||||
|
||||
def del_publish_options(self):
|
||||
|
||||
@@ -38,9 +38,8 @@ class StaticExtendedDisco(object):
|
||||
The data parameter may provide:
|
||||
data -- Either a single data form, or a list of data forms.
|
||||
"""
|
||||
with self.static.lock:
|
||||
self.del_extended_info(jid, node, ifrom, data)
|
||||
self.add_extended_info(jid, node, ifrom, data)
|
||||
self.del_extended_info(jid, node, ifrom, data)
|
||||
self.add_extended_info(jid, node, ifrom, data)
|
||||
|
||||
def add_extended_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -49,16 +48,15 @@ class StaticExtendedDisco(object):
|
||||
The data parameter may provide:
|
||||
data -- Either a single data form, or a list of data forms.
|
||||
"""
|
||||
with self.static.lock:
|
||||
self.static.add_node(jid, node)
|
||||
self.static.add_node(jid, node)
|
||||
|
||||
forms = data.get('data', [])
|
||||
if not isinstance(forms, list):
|
||||
forms = [forms]
|
||||
forms = data.get('data', [])
|
||||
if not isinstance(forms, list):
|
||||
forms = [forms]
|
||||
|
||||
info = self.static.get_node(jid, node)['info']
|
||||
for form in forms:
|
||||
info.append(form)
|
||||
info = self.static.get_node(jid, node)['info']
|
||||
for form in forms:
|
||||
info.append(form)
|
||||
|
||||
def del_extended_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -66,8 +64,7 @@ class StaticExtendedDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
with self.static.lock:
|
||||
if self.static.node_exists(jid, node):
|
||||
info = self.static.get_node(jid, node)['info']
|
||||
for form in info['substanza']:
|
||||
info.xml.remove(form.xml)
|
||||
if self.static.node_exists(jid, node):
|
||||
info = self.static.get_node(jid, node)['info']
|
||||
for form in info['substanza']:
|
||||
info.xml.remove(form.xml)
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# We don't want to have to import the entire library
|
||||
# just to get the version info for setup.py
|
||||
|
||||
__version__ = '1.2'
|
||||
__version_info__ = (1, 2)
|
||||
__version__ = '1.2.1'
|
||||
__version_info__ = (1, 2, 1)
|
||||
|
||||
@@ -1,38 +1,10 @@
|
||||
"""
|
||||
A module that monkey patches the standard asyncio module to add an
|
||||
idle_call() method to the main loop. This method is used to execute a
|
||||
callback whenever the loop is not busy handling anything else. This means
|
||||
that it is a callback with lower priority than IO, timer, or even
|
||||
call_soon() ones. These callback are called only once each.
|
||||
asyncio-related utilities
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from asyncio import events
|
||||
from functools import wraps
|
||||
|
||||
import collections
|
||||
|
||||
def idle_call(self, callback):
|
||||
if asyncio.iscoroutinefunction(callback):
|
||||
raise TypeError("coroutines cannot be used with idle_call()")
|
||||
handle = events.Handle(callback, [], self)
|
||||
self._idle.append(handle)
|
||||
|
||||
def my_run_once(self):
|
||||
if self._idle:
|
||||
self._ready.append(events.Handle(lambda: None, (), self))
|
||||
real_run_once(self)
|
||||
if self._idle:
|
||||
handle = self._idle.popleft()
|
||||
handle._run()
|
||||
|
||||
cls = asyncio.get_event_loop().__class__
|
||||
|
||||
cls._idle = collections.deque()
|
||||
cls.idle_call = idle_call
|
||||
real_run_once = cls._run_once
|
||||
cls._run_once = my_run_once
|
||||
|
||||
def future_wrapper(func):
|
||||
"""
|
||||
Make sure the result of a function call is an asyncio.Future()
|
||||
|
||||
@@ -380,7 +380,7 @@ class XMLStream(asyncio.BaseProtocol):
|
||||
elif self.xml_depth == 1:
|
||||
# A stanza is an XML element that is a direct child of
|
||||
# the root element, hence the check of depth == 1
|
||||
self.loop.idle_call(functools.partial(self.__spawn_event, xml))
|
||||
self._spawn_event(xml)
|
||||
if self.xml_root is not None:
|
||||
# Keep the root element empty of children to
|
||||
# save on memory use.
|
||||
@@ -893,7 +893,7 @@ class XMLStream(asyncio.BaseProtocol):
|
||||
stanza['lang'] = self.peer_default_lang
|
||||
return stanza
|
||||
|
||||
def __spawn_event(self, xml):
|
||||
def _spawn_event(self, xml):
|
||||
"""
|
||||
Analyze incoming XML stanzas and convert them into stanza
|
||||
objects if applicable and queue stream events to be processed
|
||||
|
||||
@@ -142,7 +142,7 @@ class TestElementBase(SlixTest):
|
||||
interfaces = set(('bar', 'baz', 'qux'))
|
||||
sub_interfaces = set(('baz',))
|
||||
|
||||
def getQux(self):
|
||||
def get_qux(self):
|
||||
return 'qux'
|
||||
|
||||
class TestStanzaPlugin(ElementBase):
|
||||
@@ -188,7 +188,7 @@ class TestElementBase(SlixTest):
|
||||
interfaces = set(('bar', 'baz', 'qux'))
|
||||
sub_interfaces = set(('baz',))
|
||||
|
||||
def setQux(self, value):
|
||||
def set_qux(self, value):
|
||||
pass
|
||||
|
||||
class TestStanzaPlugin(ElementBase):
|
||||
@@ -222,7 +222,7 @@ class TestElementBase(SlixTest):
|
||||
interfaces = set(('bar', 'baz', 'qux'))
|
||||
sub_interfaces = set(('bar',))
|
||||
|
||||
def delQux(self):
|
||||
def del_qux(self):
|
||||
pass
|
||||
|
||||
class TestStanzaPlugin(ElementBase):
|
||||
@@ -300,14 +300,14 @@ class TestElementBase(SlixTest):
|
||||
namespace = "foo"
|
||||
interfaces = set(('bar',))
|
||||
|
||||
def setBar(self, value):
|
||||
def set_bar(self, value):
|
||||
wrapper = ET.Element("{foo}wrapper")
|
||||
bar = ET.Element("{foo}bar")
|
||||
bar.text = value
|
||||
wrapper.append(bar)
|
||||
self.xml.append(wrapper)
|
||||
|
||||
def getBar(self):
|
||||
def get_bar(self):
|
||||
return self._get_sub_text("wrapper/bar", default="not found")
|
||||
|
||||
stanza = TestStanza()
|
||||
@@ -333,16 +333,16 @@ class TestElementBase(SlixTest):
|
||||
namespace = "foo"
|
||||
interfaces = set(('bar', 'baz'))
|
||||
|
||||
def setBaz(self, value):
|
||||
def set_baz(self, value):
|
||||
self._set_sub_text("wrapper/baz", text=value)
|
||||
|
||||
def getBaz(self):
|
||||
def get_baz(self):
|
||||
return self._get_sub_text("wrapper/baz")
|
||||
|
||||
def setBar(self, value):
|
||||
def set_bar(self, value):
|
||||
self._set_sub_text("wrapper/bar", text=value)
|
||||
|
||||
def getBar(self):
|
||||
def get_bar(self):
|
||||
return self._get_sub_text("wrapper/bar")
|
||||
|
||||
stanza = TestStanza()
|
||||
@@ -384,22 +384,22 @@ class TestElementBase(SlixTest):
|
||||
namespace = "foo"
|
||||
interfaces = set(('bar', 'baz'))
|
||||
|
||||
def setBar(self, value):
|
||||
def set_bar(self, value):
|
||||
self._set_sub_text("path/to/only/bar", value)
|
||||
|
||||
def getBar(self):
|
||||
def get_bar(self):
|
||||
return self._get_sub_text("path/to/only/bar")
|
||||
|
||||
def delBar(self):
|
||||
def del_bar(self):
|
||||
self._del_sub("path/to/only/bar")
|
||||
|
||||
def setBaz(self, value):
|
||||
def set_baz(self, value):
|
||||
self._set_sub_text("path/to/just/baz", value)
|
||||
|
||||
def getBaz(self):
|
||||
def get_baz(self):
|
||||
return self._get_sub_text("path/to/just/baz")
|
||||
|
||||
def delBaz(self):
|
||||
def del_baz(self):
|
||||
self._del_sub("path/to/just/baz")
|
||||
|
||||
stanza = TestStanza()
|
||||
@@ -466,10 +466,10 @@ class TestElementBase(SlixTest):
|
||||
interfaces = set(('bar','baz', 'qux'))
|
||||
sub_interfaces = set(('qux',))
|
||||
|
||||
def setQux(self, value):
|
||||
def set_qux(self, value):
|
||||
self._set_sub_text('qux', text=value)
|
||||
|
||||
def getQux(self):
|
||||
def get_qux(self):
|
||||
return self._get_sub_text('qux')
|
||||
|
||||
class TestStanzaPlugin(ElementBase):
|
||||
|
||||
@@ -20,12 +20,6 @@ class TestMessageStanzas(SlixTest):
|
||||
msg = msg.reply()
|
||||
self.failUnless(str(msg['to']) == 'room@someservice.someserver.tld')
|
||||
|
||||
def testAttribProperty(self):
|
||||
"Test attrib property returning self"
|
||||
msg = self.Message()
|
||||
msg.attrib.attrib.attrib['to'] = 'usr@server.tld'
|
||||
self.failUnless(str(msg['to']) == 'usr@server.tld')
|
||||
|
||||
def testHTMLPlugin(self):
|
||||
"Test message/html/body stanza"
|
||||
msg = self.Message()
|
||||
|
||||
@@ -136,11 +136,11 @@ class TestPubsubStanzas(SlixTest):
|
||||
iq = self.Iq()
|
||||
iq['pubsub_owner']['default']
|
||||
iq['pubsub_owner']['default']['node'] = 'mynode'
|
||||
iq['pubsub_owner']['default']['form'].addField('pubsub#title',
|
||||
iq['pubsub_owner']['default']['form'].add_field('pubsub#title',
|
||||
ftype='text-single',
|
||||
value='This thing is awesome')
|
||||
self.check(iq, """
|
||||
<iq id="0">
|
||||
<iq id="0">
|
||||
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
||||
<default node="mynode">
|
||||
<x xmlns="jabber:x:data" type="form">
|
||||
@@ -161,7 +161,8 @@ class TestPubsubStanzas(SlixTest):
|
||||
iq['pubsub']['subscribe']['options']['node'] = 'cheese'
|
||||
iq['pubsub']['subscribe']['options']['jid'] = 'fritzy@netflint.net/slixmpp'
|
||||
form = xep_0004.Form()
|
||||
form.addField('pubsub#title', ftype='text-single', value='this thing is awesome')
|
||||
form['type'] = 'submit'
|
||||
form.add_field('pubsub#title', ftype='text-single', value='this thing is awesome')
|
||||
iq['pubsub']['subscribe']['options']['options'] = form
|
||||
self.check(iq, """
|
||||
<iq id="0">
|
||||
@@ -201,6 +202,7 @@ class TestPubsubStanzas(SlixTest):
|
||||
iq['pubsub']['publish'].append(item)
|
||||
iq['pubsub']['publish'].append(item2)
|
||||
form = xep_0004.Form()
|
||||
form['type'] = 'submit'
|
||||
form.addField('pubsub#description', ftype='text-single', value='this thing is awesome')
|
||||
iq['pubsub']['publish_options'] = form
|
||||
|
||||
@@ -253,7 +255,7 @@ class TestPubsubStanzas(SlixTest):
|
||||
pub = iq['pubsub']
|
||||
pub['create']['node'] = 'testnode2'
|
||||
pub['configure']['form']['type'] = 'submit'
|
||||
pub['configure']['form'].setFields([
|
||||
pub['configure']['form'].set_fields([
|
||||
('FORM_TYPE', {'type': 'hidden',
|
||||
'value': 'http://jabber.org/protocol/pubsub#node_config'}),
|
||||
('pubsub#node_type', {'type': 'list-single',
|
||||
|
||||
Reference in New Issue
Block a user