From c66a4d4097a249efc029b761d6150378a54bf702 Mon Sep 17 00:00:00 2001 From: mathieui Date: Tue, 24 Feb 2015 18:58:40 +0100 Subject: Update the documentation and examples - update most of the examples with slixmpp - change the help channels pointed out in the doc - add a page listing differences from slixmpp and how to use asyncio nicely with slixmpp - fix some in-code rst documentation --- examples/IoT_TestDevice.py | 14 +++----------- examples/disco_browser.py | 20 ++++++++++--------- examples/download_avatars.py | 29 ++++++++++++++++++++-------- examples/migrate_roster.py | 4 ++-- examples/ping.py | 10 ++++++---- examples/pubsub_client.py | 26 ++++++++++++++++++------- examples/register_account.py | 2 +- examples/roster_browser.py | 13 +++++++++---- examples/rpc_async.py | 2 +- examples/set_avatar.py | 46 ++++++++++++++++++++++---------------------- 10 files changed, 96 insertions(+), 70 deletions(-) (limited to 'examples') diff --git a/examples/IoT_TestDevice.py b/examples/IoT_TestDevice.py index b1968175..5b72994c 100755 --- a/examples/IoT_TestDevice.py +++ b/examples/IoT_TestDevice.py @@ -11,20 +11,12 @@ See the file LICENSE for copying permission. """ -import os -import sys -# This can be used when you are in a test environment and need to make paths right -sys.path=['/Users/jocke/Dropbox/06_dev/Slixmpp']+sys.path - import logging -import unittest -import distutils.core -import datetime -from glob import glob -from os.path import splitext, basename, join as pjoin +from os.path import basename, join as pjoin from argparse import ArgumentParser from urllib import urlopen +from getpass import getpass import slixmpp from slixmpp.plugins.xep_0323.device import Device @@ -186,5 +178,5 @@ if __name__ == '__main__': logging.debug("ready ending") else: - print "noopp didn't happen" + print("noopp didn't happen") diff --git a/examples/disco_browser.py b/examples/disco_browser.py index 33134c99..796562f2 100755 --- a/examples/disco_browser.py +++ b/examples/disco_browser.py @@ -15,6 +15,7 @@ from argparse import ArgumentParser import slixmpp from slixmpp.exceptions import IqError, IqTimeout +from slixmpp.xmlstream.asyncio import asyncio class Disco(slixmpp.ClientXMPP): @@ -53,6 +54,7 @@ class Disco(slixmpp.ClientXMPP): # our roster. self.add_event_handler("session_start", self.start) + @asyncio.coroutine def start(self, event): """ Process the session_start event. @@ -79,17 +81,17 @@ class Disco(slixmpp.ClientXMPP): # received. Non-blocking options would be to listen # for the disco_info event, or passing a handler # function using the callback parameter. - info = self['xep_0030'].get_info(jid=self.target_jid, - node=self.target_node, - block=True) - elif self.get in self.items_types: + info = yield from self['xep_0030'].get_info(jid=self.target_jid, + node=self.target_node, + coroutine=True) + if self.get in self.items_types: # The same applies from above. Listen for the # disco_items event or pass a callback function # if you need to process a non-blocking request. - items = self['xep_0030'].get_items(jid=self.target_jid, - node=self.target_node, - block=True) - else: + items = yield from self['xep_0030'].get_items(jid=self.target_jid, + node=self.target_node, + coroutine=True) + if self.get not in self.info_types and self.get not in self.items_types: logging.error("Invalid disco request type.") return except IqError as e: @@ -143,7 +145,7 @@ if __name__ == '__main__': parser.add_argument("-p", "--password", dest="password", help="password to use") parser.add_argument("query", choices=["all", "info", "items", "identities", "features"]) - parser.add_argument("target-jid") + parser.add_argument("target_jid") parser.add_argument("node", nargs='?') args = parser.parse_args() diff --git a/examples/download_avatars.py b/examples/download_avatars.py index c6d8c59c..1d7d72f8 100755 --- a/examples/download_avatars.py +++ b/examples/download_avatars.py @@ -11,11 +11,11 @@ import logging from getpass import getpass -import threading from argparse import ArgumentParser import slixmpp from slixmpp.exceptions import XMPPError +from slixmpp import asyncio FILE_TYPES = { @@ -40,8 +40,14 @@ class AvatarDownloader(slixmpp.ClientXMPP): self.add_event_handler('avatar_metadata_publish', self.on_avatar) self.received = set() - self.presences_received = threading.Event() + self.presences_received = asyncio.Event() + self.roster_received = asyncio.Event() + def roster_received_cb(self, event): + self.roster_received.set() + self.presences_received.clear() + + @asyncio.coroutine def start(self, event): """ Process the session_start event. @@ -56,16 +62,20 @@ class AvatarDownloader(slixmpp.ClientXMPP): data. """ self.send_presence() - self.get_roster() + self.get_roster(callback=self.roster_received_cb) print('Waiting for presence updates...\n') - self.presences_received.wait(15) + yield from self.roster_received.wait() + print('Roster received') + yield from self.presences_received.wait() self.disconnect() + @asyncio.coroutine def on_vcard_avatar(self, pres): print("Received vCard avatar update from %s" % pres['from'].bare) try: - result = self['xep_0054'].get_vcard(pres['from'], cached=True) + result = yield from self['xep_0054'].get_vcard(pres['from'].bare, cached=True, + coroutine=True, timeout=5) except XMPPError: print("Error retrieving avatar for %s" % pres['from']) return @@ -76,16 +86,18 @@ class AvatarDownloader(slixmpp.ClientXMPP): pres['from'].bare, pres['vcard_temp_update']['photo'], filetype) - with open(filename, 'w+') as img: + with open(filename, 'wb+') as img: img.write(avatar['BINVAL']) + @asyncio.coroutine def on_avatar(self, msg): print("Received avatar update from %s" % msg['from']) metadata = msg['pubsub_event']['items']['item']['avatar_metadata'] for info in metadata['items']: if not info['url']: try: - result = self['xep_0084'].retrieve_avatar(msg['from'], info['id']) + result = yield from self['xep_0084'].retrieve_avatar(msg['from'].bare, info['id'], + coroutine=True, timeout=5) except XMPPError: print("Error retrieving avatar for %s" % msg['from']) return @@ -94,7 +106,7 @@ class AvatarDownloader(slixmpp.ClientXMPP): filetype = FILE_TYPES.get(metadata['type'], 'png') filename = 'avatar_%s_%s.%s' % (msg['from'].bare, info['id'], filetype) - with open(filename, 'w+') as img: + with open(filename, 'wb+') as img: img.write(avatar['value']) else: # We could retrieve the avatar via HTTP, etc here instead. @@ -105,6 +117,7 @@ class AvatarDownloader(slixmpp.ClientXMPP): Wait to receive updates from all roster contacts. """ self.received.add(pres['from'].bare) + print((len(self.received), len(self.client_roster.keys()))) if len(self.received) >= len(self.client_roster.keys()): self.presences_received.set() else: diff --git a/examples/migrate_roster.py b/examples/migrate_roster.py index bd3bf7e6..e6c66f2e 100755 --- a/examples/migrate_roster.py +++ b/examples/migrate_roster.py @@ -103,5 +103,5 @@ def on_session2(event): new_xmpp.disconnect() new_xmpp.add_event_handler('session_start', on_session2) -if new_xmpp.connect(): - new_xmpp.process(block=True) +new_xmpp.connect() +new_xmpp.process() diff --git a/examples/ping.py b/examples/ping.py index 06b03c51..39118ac4 100755 --- a/examples/ping.py +++ b/examples/ping.py @@ -12,6 +12,8 @@ import logging from getpass import getpass from argparse import ArgumentParser +from slixmpp.exceptions import IqError, IqTimeout +from slixmpp import asyncio import slixmpp @@ -36,6 +38,7 @@ class PingTest(slixmpp.ClientXMPP): # our roster. self.add_event_handler("session_start", self.start) + @asyncio.coroutine def start(self, event): """ Process the session_start event. @@ -53,8 +56,8 @@ class PingTest(slixmpp.ClientXMPP): self.get_roster() try: - rtt = self['xep_0199'].ping(self.pingjid, - timeout=10) + rtt = yield from self['xep_0199'].ping(self.pingjid, + timeout=10) logging.info("Success! RTT: %s", rtt) except IqError as e: logging.info("Error pinging %s: %s", @@ -78,8 +81,7 @@ if __name__ == '__main__': action="store_const", dest="loglevel", const=logging.DEBUG, default=logging.INFO) parser.add_argument("-t", "--pingto", help="set jid to ping", - action="store", type="string", dest="pingjid", - default=None) + dest="pingjid", default=None) # JID and password options. parser.add_argument("-j", "--jid", dest="jid", diff --git a/examples/pubsub_client.py b/examples/pubsub_client.py index fd215efd..b379af95 100755 --- a/examples/pubsub_client.py +++ b/examples/pubsub_client.py @@ -7,7 +7,13 @@ from argparse import ArgumentParser import slixmpp from slixmpp.xmlstream import ET, tostring +from slixmpp.xmlstream.asyncio import asyncio +def make_callback(): + future = asyncio.Future() + def callback(result): + future.set_result(result) + return future, callback class PubsubClient(slixmpp.ClientXMPP): @@ -41,8 +47,10 @@ class PubsubClient(slixmpp.ClientXMPP): self.disconnect() def nodes(self): + future, callback = make_callback() try: - result = self['xep_0060'].get_nodes(self.pubsub_server, self.node) + self['xep_0060'].get_nodes(self.pubsub_server, self.node, callback=callback) + result = yield from future for item in result['disco_items']['items']: print(' - %s' % str(item)) except: @@ -63,16 +71,20 @@ class PubsubClient(slixmpp.ClientXMPP): def publish(self): payload = ET.fromstring("%s" % self.data) + future, callback = make_callback() try: - result = self['xep_0060'].publish(self.pubsub_server, self.node, payload=payload) + self['xep_0060'].publish(self.pubsub_server, self.node, payload=payload, callback=callback) + result = yield from future id = result['pubsub']['publish']['item']['id'] print('Published at item id: %s' % id) except: logging.error('Could not publish to: %s' % self.node) def get(self): + future, callback = make_callback() try: - result = self['xep_0060'].get_item(self.pubsub_server, self.node, self.data) + self['xep_0060'].get_item(self.pubsub_server, self.node, self.data, callback=callback) + result = yield from future for item in result['pubsub']['items']['substanzas']: print('Retrieved item %s: %s' % (item['id'], tostring(item['payload']))) except: @@ -80,28 +92,28 @@ class PubsubClient(slixmpp.ClientXMPP): def retract(self): try: - result = self['xep_0060'].retract(self.pubsub_server, self.node, self.data) + self['xep_0060'].retract(self.pubsub_server, self.node, self.data) print('Retracted item %s from node %s' % (self.data, self.node)) except: logging.error('Could not retract item %s from node %s' % (self.data, self.node)) def purge(self): try: - result = self['xep_0060'].purge(self.pubsub_server, self.node) + self['xep_0060'].purge(self.pubsub_server, self.node) print('Purged all items from node %s' % self.node) except: logging.error('Could not purge items from node %s' % self.node) def subscribe(self): try: - result = self['xep_0060'].subscribe(self.pubsub_server, self.node) + self['xep_0060'].subscribe(self.pubsub_server, self.node) print('Subscribed %s to node %s' % (self.boundjid.bare, self.node)) except: logging.error('Could not subscribe %s to node %s' % (self.boundjid.bare, self.node)) def unsubscribe(self): try: - result = self['xep_0060'].unsubscribe(self.pubsub_server, self.node) + self['xep_0060'].unsubscribe(self.pubsub_server, self.node) print('Unsubscribed %s from node %s' % (self.boundjid.bare, self.node)) except: logging.error('Could not unsubscribe %s from node %s' % (self.boundjid.bare, self.node)) diff --git a/examples/register_account.py b/examples/register_account.py index 9d6e3b8f..1cfc8c72 100755 --- a/examples/register_account.py +++ b/examples/register_account.py @@ -90,7 +90,7 @@ class RegisterBot(slixmpp.ClientXMPP): resp['register']['password'] = self.password try: - resp.send() + yield from resp.send_coroutine() logging.info("Account created for %s!" % self.boundjid) except IqError as e: logging.error("Could not register account: %s" % diff --git a/examples/roster_browser.py b/examples/roster_browser.py index 74d2839a..4d07de11 100755 --- a/examples/roster_browser.py +++ b/examples/roster_browser.py @@ -11,11 +11,11 @@ import logging from getpass import getpass -import threading from argparse import ArgumentParser import slixmpp from slixmpp.exceptions import IqError, IqTimeout +from slixmpp.xmlstream.asyncio import asyncio class RosterBrowser(slixmpp.ClientXMPP): @@ -36,8 +36,9 @@ class RosterBrowser(slixmpp.ClientXMPP): self.add_event_handler("changed_status", self.wait_for_presences) self.received = set() - self.presences_received = threading.Event() + self.presences_received = asyncio.Event() + @asyncio.coroutine def start(self, event): """ Process the session_start event. @@ -51,8 +52,12 @@ class RosterBrowser(slixmpp.ClientXMPP): event does not provide any additional data. """ + future = asyncio.Future() + def callback(result): + future.set_result(None) try: - self.get_roster() + self.get_roster(callback=callback) + yield from future except IqError as err: print('Error: %' % err.iq['error']['condition']) except IqTimeout: @@ -61,7 +66,7 @@ class RosterBrowser(slixmpp.ClientXMPP): print('Waiting for presence updates...\n') - self.presences_received.wait(5) + yield from asyncio.sleep(10) print('Roster for %s' % self.boundjid.bare) groups = self.client_roster.groups() diff --git a/examples/rpc_async.py b/examples/rpc_async.py index 6798d63c..f773a8d1 100755 --- a/examples/rpc_async.py +++ b/examples/rpc_async.py @@ -20,7 +20,7 @@ class Boomerang(Endpoint): @remote def throw(self): - print "Duck!" + print("Duck!") diff --git a/examples/set_avatar.py b/examples/set_avatar.py index 9a050e5a..5805d18a 100755 --- a/examples/set_avatar.py +++ b/examples/set_avatar.py @@ -18,7 +18,7 @@ from argparse import ArgumentParser import slixmpp from slixmpp.exceptions import XMPPError - +from slixmpp import asyncio class AvatarSetter(slixmpp.ClientXMPP): @@ -33,6 +33,7 @@ class AvatarSetter(slixmpp.ClientXMPP): self.filepath = filepath + @asyncio.coroutine def start(self, event): """ Process the session_start event. @@ -51,7 +52,7 @@ class AvatarSetter(slixmpp.ClientXMPP): avatar_file = None try: - avatar_file = open(os.path.expanduser(self.filepath)) + avatar_file = open(os.path.expanduser(self.filepath), 'rb') except IOError: print('Could not find file: %s' % self.filepath) return self.disconnect() @@ -65,32 +66,31 @@ class AvatarSetter(slixmpp.ClientXMPP): avatar_file.close() used_xep84 = False - try: - print('Publish XEP-0084 avatar data') - self['xep_0084'].publish_avatar(avatar) - used_xep84 = True - except XMPPError: + + print('Publish XEP-0084 avatar data') + result = yield from self['xep_0084'].publish_avatar(avatar, coroutine=True) + if isinstance(result, XMPPError): print('Could not publish XEP-0084 avatar') + else: + used_xep84 = True - try: - print('Update vCard with avatar') - self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type) - except XMPPError: + print('Update vCard with avatar') + result = yield from self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type, coroutine=True) + if isinstance(result, XMPPError): print('Could not set vCard avatar') if used_xep84: - try: - print('Advertise XEP-0084 avatar metadata') - self['xep_0084'].publish_avatar_metadata([ - {'id': avatar_id, - 'type': avatar_type, - 'bytes': avatar_bytes} - # We could advertise multiple avatars to provide - # options in image type, source (HTTP vs pubsub), - # size, etc. - # {'id': ....} - ]) - except XMPPError: + print('Advertise XEP-0084 avatar metadata') + result = yield from self['xep_0084'].publish_avatar_metadata([ + {'id': avatar_id, + 'type': avatar_type, + 'bytes': avatar_bytes} + # We could advertise multiple avatars to provide + # options in image type, source (HTTP vs pubsub), + # size, etc. + # {'id': ....} + ], coroutine=True) + if isinstance(result, XMPPError): print('Could not publish XEP-0084 metadata') print('Wait for presence updates to propagate...') -- cgit v1.2.3