diff options
Diffstat (limited to 'sleekxmpp/basexmpp.py')
-rw-r--r-- | sleekxmpp/basexmpp.py | 831 |
1 files changed, 0 insertions, 831 deletions
diff --git a/sleekxmpp/basexmpp.py b/sleekxmpp/basexmpp.py deleted file mode 100644 index cb72b9bd..00000000 --- a/sleekxmpp/basexmpp.py +++ /dev/null @@ -1,831 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sleekxmpp.basexmpp - ~~~~~~~~~~~~~~~~~~ - - This module provides the common XMPP functionality - for both clients and components. - - Part of SleekXMPP: The Sleek XMPP Library - - :copyright: (c) 2011 Nathanael C. Fritz - :license: MIT, see LICENSE for more details -""" - -from __future__ import with_statement, unicode_literals - -import sys -import logging -import threading - -from sleekxmpp import plugins, roster, stanza -from sleekxmpp.api import APIRegistry -from sleekxmpp.exceptions import IqError, IqTimeout - -from sleekxmpp.stanza import Message, Presence, Iq, StreamError -from sleekxmpp.stanza.roster import Roster -from sleekxmpp.stanza.nick import Nick - -from sleekxmpp.xmlstream import XMLStream, JID -from sleekxmpp.xmlstream import ET, register_stanza_plugin -from sleekxmpp.xmlstream.matcher import MatchXPath -from sleekxmpp.xmlstream.handler import Callback -from sleekxmpp.xmlstream.stanzabase import XML_NS - -from sleekxmpp.plugins import PluginManager, load_plugin - - -log = logging.getLogger(__name__) - -# In order to make sure that Unicode is handled properly -# in Python 2.x, reset the default encoding. -if sys.version_info < (3, 0): - from sleekxmpp.util.misc_ops import setdefaultencoding - setdefaultencoding('utf8') - - -class BaseXMPP(XMLStream): - - """ - The BaseXMPP class adapts the generic XMLStream class for use - with XMPP. It also provides a plugin mechanism to easily extend - and add support for new XMPP features. - - :param default_ns: Ensure that the correct default XML namespace - is used during initialization. - """ - - def __init__(self, jid='', default_ns='jabber:client', **kwargs): - XMLStream.__init__(self, **kwargs) - - self.default_ns = default_ns - self.stream_ns = 'http://etherx.jabber.org/streams' - self.namespace_map[self.stream_ns] = 'stream' - - #: An identifier for the stream as given by the server. - self.stream_id = None - - #: The JabberID (JID) requested for this connection. - self.requested_jid = JID(jid, cache_lock=True) - - #: The JabberID (JID) used by this connection, - #: as set after session binding. This may even be a - #: different bare JID than what was requested. - self.boundjid = JID(jid, cache_lock=True) - - self._expected_server_name = self.boundjid.host - self._redirect_attempts = 0 - - #: The maximum number of consecutive see-other-host - #: redirections that will be followed before quitting. - self.max_redirects = 5 - - self.session_bind_event = threading.Event() - - #: A dictionary mapping plugin names to plugins. - self.plugin = PluginManager(self) - - #: Configuration options for whitelisted plugins. - #: If a plugin is registered without any configuration, - #: and there is an entry here, it will be used. - self.plugin_config = {} - - #: A list of plugins that will be loaded if - #: :meth:`register_plugins` is called. - self.plugin_whitelist = [] - - #: The main roster object. This roster supports multiple - #: owner JIDs, as in the case for components. For clients - #: which only have a single JID, see :attr:`client_roster`. - self.roster = roster.Roster(self) - self.roster.add(self.boundjid) - - #: The single roster for the bound JID. This is the - #: equivalent of:: - #: - #: self.roster[self.boundjid.bare] - self.client_roster = self.roster[self.boundjid] - - #: The distinction between clients and components can be - #: important, primarily for choosing how to handle the - #: ``'to'`` and ``'from'`` JIDs of stanzas. - self.is_component = False - - #: Messages may optionally be tagged with ID values. Setting - #: :attr:`use_message_ids` to `True` will assign all outgoing - #: messages an ID. Some plugin features require enabling - #: this option. - self.use_message_ids = False - - #: Presence updates may optionally be tagged with ID values. - #: Setting :attr:`use_message_ids` to `True` will assign all - #: outgoing messages an ID. - self.use_presence_ids = False - - #: The API registry is a way to process callbacks based on - #: JID+node combinations. Each callback in the registry is - #: marked with: - #: - #: - An API name, e.g. xep_0030 - #: - The name of an action, e.g. get_info - #: - The JID that will be affected - #: - The node that will be affected - #: - #: API handlers with no JID or node will act as global handlers, - #: while those with a JID and no node will service all nodes - #: for a JID, and handlers with both a JID and node will be - #: used only for that specific combination. The handler that - #: provides the most specificity will be used. - self.api = APIRegistry(self) - - #: Flag indicating that the initial presence broadcast has - #: been sent. Until this happens, some servers may not - #: behave as expected when sending stanzas. - self.sentpresence = False - - #: A reference to :mod:`sleekxmpp.stanza` to make accessing - #: stanza classes easier. - self.stanza = stanza - - self.register_handler( - Callback('IM', - MatchXPath('{%s}message/{%s}body' % (self.default_ns, - self.default_ns)), - self._handle_message)) - self.register_handler( - Callback('Presence', - MatchXPath("{%s}presence" % self.default_ns), - self._handle_presence)) - - self.register_handler( - Callback('Stream Error', - MatchXPath("{%s}error" % self.stream_ns), - self._handle_stream_error)) - - self.add_event_handler('session_start', - self._handle_session_start) - self.add_event_handler('disconnected', - self._handle_disconnected) - self.add_event_handler('presence_available', - self._handle_available) - self.add_event_handler('presence_dnd', - self._handle_available) - self.add_event_handler('presence_xa', - self._handle_available) - self.add_event_handler('presence_chat', - self._handle_available) - self.add_event_handler('presence_away', - self._handle_available) - self.add_event_handler('presence_unavailable', - self._handle_unavailable) - self.add_event_handler('presence_subscribe', - self._handle_subscribe) - self.add_event_handler('presence_subscribed', - self._handle_subscribed) - self.add_event_handler('presence_unsubscribe', - self._handle_unsubscribe) - self.add_event_handler('presence_unsubscribed', - self._handle_unsubscribed) - self.add_event_handler('roster_subscription_request', - self._handle_new_subscription) - - # Set up the XML stream with XMPP's root stanzas. - self.register_stanza(Message) - self.register_stanza(Iq) - self.register_stanza(Presence) - self.register_stanza(StreamError) - - # Initialize a few default stanza plugins. - register_stanza_plugin(Iq, Roster) - register_stanza_plugin(Message, Nick) - - def start_stream_handler(self, xml): - """Save the stream ID once the streams have been established. - - :param xml: The incoming stream's root element. - """ - self.stream_id = xml.get('id', '') - self.stream_version = xml.get('version', '') - self.peer_default_lang = xml.get('{%s}lang' % XML_NS, None) - - if not self.is_component and not self.stream_version: - log.warning('Legacy XMPP 0.9 protocol detected.') - self.event('legacy_protocol') - - def process(self, *args, **kwargs): - """Initialize plugins and begin processing the XML stream. - - The number of threads used for processing stream events is determined - by :data:`HANDLER_THREADS`. - - :param bool block: If ``False``, then event dispatcher will run - in a separate thread, allowing for the stream to be - used in the background for another application. - Otherwise, ``process(block=True)`` blocks the current - thread. Defaults to ``False``. - :param bool threaded: **DEPRECATED** - If ``True``, then event dispatcher will run - in a separate thread, allowing for the stream to be - used in the background for another application. - Defaults to ``True``. This does **not** mean that no - threads are used at all if ``threaded=False``. - - Regardless of these threading options, these threads will - always exist: - - - The event queue processor - - The send queue processor - - The scheduler - """ - for name in self.plugin: - if not hasattr(self.plugin[name], 'post_inited'): - if hasattr(self.plugin[name], 'post_init'): - self.plugin[name].post_init() - self.plugin[name].post_inited = True - return XMLStream.process(self, *args, **kwargs) - - def register_plugin(self, plugin, pconfig=None, module=None): - """Register and configure a plugin for use in this stream. - - :param plugin: The name of the plugin class. Plugin names must - be unique. - :param pconfig: A dictionary of configuration data for the plugin. - Defaults to an empty dictionary. - :param module: Optional refence to the module containing the plugin - class if using custom plugins. - """ - - # Use the global plugin config cache, if applicable - if not pconfig: - pconfig = self.plugin_config.get(plugin, {}) - - if not self.plugin.registered(plugin): - load_plugin(plugin, module) - self.plugin.enable(plugin, pconfig) - - def register_plugins(self): - """Register and initialize all built-in plugins. - - Optionally, the list of plugins loaded may be limited to those - contained in :attr:`plugin_whitelist`. - - Plugin configurations stored in :attr:`plugin_config` will be used. - """ - if self.plugin_whitelist: - plugin_list = self.plugin_whitelist - else: - plugin_list = plugins.__all__ - - for plugin in plugin_list: - if plugin in plugins.__all__: - self.register_plugin(plugin) - else: - raise NameError("Plugin %s not in plugins.__all__." % plugin) - - def __getitem__(self, key): - """Return a plugin given its name, if it has been registered.""" - if key in self.plugin: - return self.plugin[key] - else: - log.warning("Plugin '%s' is not loaded.", key) - return False - - def get(self, key, default): - """Return a plugin given its name, if it has been registered.""" - return self.plugin.get(key, default) - - def Message(self, *args, **kwargs): - """Create a Message stanza associated with this stream.""" - msg = Message(self, *args, **kwargs) - msg['lang'] = self.default_lang - return msg - - def Iq(self, *args, **kwargs): - """Create an Iq stanza associated with this stream.""" - return Iq(self, *args, **kwargs) - - def Presence(self, *args, **kwargs): - """Create a Presence stanza associated with this stream.""" - pres = Presence(self, *args, **kwargs) - pres['lang'] = self.default_lang - return pres - - 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. - - :param id: An ideally unique ID value for this stanza thread. - Defaults to 0. - :param ifrom: The from :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param itype: The :class:`~sleekxmpp.stanza.iq.Iq`'s type, - one of: ``'get'``, ``'set'``, ``'result'``, - or ``'error'``. - :param 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'] = iquery - return iq - - def make_iq_get(self, queryxmlns=None, ito=None, ifrom=None, iq=None): - """Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type ``'get'``. - - Optionally, a query element may be added. - - :param queryxmlns: The namespace of the query to use. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param ifrom: The ``'from'`` :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - :param iq: Optionally use an existing stanza instead - of generating a new one. - """ - if not iq: - iq = self.Iq() - iq['type'] = 'get' - iq['query'] = queryxmlns - if ito: - iq['to'] = ito - if ifrom: - iq['from'] = ifrom - return iq - - def make_iq_result(self, id=None, ito=None, ifrom=None, iq=None): - """ - Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type - ``'result'`` with the given ID value. - - :param id: An ideally unique ID value. May use :meth:`new_id()`. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param ifrom: The ``'from'`` :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - :param iq: Optionally use an existing stanza instead - of generating a new one. - """ - if not iq: - iq = self.Iq() - if id is None: - id = self.new_id() - iq['id'] = id - iq['type'] = 'result' - if ito: - iq['to'] = ito - if ifrom: - iq['from'] = ifrom - return iq - - def make_iq_set(self, sub=None, ito=None, ifrom=None, iq=None): - """ - Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type ``'set'``. - - Optionally, a substanza may be given to use as the - stanza's payload. - - :param sub: Either an - :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase` - stanza object or an - :class:`~xml.etree.ElementTree.Element` XML object - to use as the :class:`~sleekxmpp.stanza.iq.Iq`'s payload. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param ifrom: The ``'from'`` :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - :param iq: Optionally use an existing stanza instead - of generating a new one. - """ - if not iq: - iq = self.Iq() - iq['type'] = 'set' - if sub != None: - iq.append(sub) - if ito: - iq['to'] = ito - if ifrom: - iq['from'] = ifrom - return iq - - def make_iq_error(self, id, type='cancel', - condition='feature-not-implemented', - text=None, ito=None, ifrom=None, iq=None): - """ - Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type ``'error'``. - - :param id: An ideally unique ID value. May use :meth:`new_id()`. - :param type: The type of the error, such as ``'cancel'`` or - ``'modify'``. Defaults to ``'cancel'``. - :param condition: The error condition. Defaults to - ``'feature-not-implemented'``. - :param text: A message describing the cause of the error. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param ifrom: The ``'from'`` :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - :param iq: Optionally use an existing stanza instead - of generating a new one. - """ - if not iq: - iq = self.Iq() - iq['id'] = id - iq['error']['type'] = type - iq['error']['condition'] = condition - iq['error']['text'] = text - if ito: - iq['to'] = ito - if ifrom: - iq['from'] = ifrom - return iq - - def make_iq_query(self, iq=None, xmlns='', ito=None, ifrom=None): - """ - Create or modify an :class:`~sleekxmpp.stanza.iq.Iq` stanza - to use the given query namespace. - - :param iq: Optionally use an existing stanza instead - of generating a new one. - :param xmlns: The query's namespace. - :param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID` - for this stanza. - :param ifrom: The ``'from'`` :class:`~sleekxmpp.xmlstream.jid.JID` - to use for this stanza. - """ - if not iq: - iq = self.Iq() - iq['query'] = xmlns - if ito: - iq['to'] = ito - if ifrom: - iq['from'] = ifrom - return iq - - def make_query_roster(self, iq=None): - """Create a roster query element. - - :param iq: Optionally use an existing stanza instead - of generating a new one. - """ - if iq: - iq['query'] = 'jabber:iq:roster' - return ET.Element("{jabber:iq:roster}query") - - def make_message(self, mto, mbody=None, msubject=None, mtype=None, - mhtml=None, mfrom=None, mnick=None): - """ - Create and initialize a new - :class:`~sleekxmpp.stanza.message.Message` stanza. - - :param mto: The recipient of the message. - :param mbody: The main contents of the message. - :param msubject: Optional subject for the message. - :param mtype: The message's type, such as ``'chat'`` or - ``'groupchat'``. - :param mhtml: Optional HTML body content in the form of a string. - :param mfrom: The sender of the message. if sending from a client, - be aware that some servers require that the full JID - of the sender be used. - :param mnick: Optional nickname of the sender. - """ - message = self.Message(sto=mto, stype=mtype, sfrom=mfrom) - message['body'] = mbody - message['subject'] = msubject - if mnick is not None: - message['nick'] = mnick - if mhtml is not None: - message['html']['body'] = mhtml - return message - - def make_presence(self, pshow=None, pstatus=None, ppriority=None, - pto=None, ptype=None, pfrom=None, pnick=None): - """ - Create and initialize a new - :class:`~sleekxmpp.stanza.presence.Presence` stanza. - - :param pshow: The presence's show value. - :param pstatus: The presence's status message. - :param ppriority: This connection's priority. - :param pto: The recipient of a directed presence. - :param ptype: The type of presence, such as ``'subscribe'``. - :param pfrom: The sender of the presence. - :param pnick: Optional nickname of the presence's sender. - """ - presence = self.Presence(stype=ptype, sfrom=pfrom, sto=pto) - if pshow is not None: - presence['type'] = pshow - if pfrom is None and self.is_component: - presence['from'] = self.boundjid.full - presence['priority'] = ppriority - presence['status'] = pstatus - presence['nick'] = pnick - return presence - - def send_message(self, mto, mbody, msubject=None, mtype=None, - mhtml=None, mfrom=None, mnick=None): - """ - Create, initialize, and send a new - :class:`~sleekxmpp.stanza.message.Message` stanza. - - :param mto: The recipient of the message. - :param mbody: The main contents of the message. - :param msubject: Optional subject for the message. - :param mtype: The message's type, such as ``'chat'`` or - ``'groupchat'``. - :param mhtml: Optional HTML body content in the form of a string. - :param mfrom: The sender of the message. if sending from a client, - be aware that some servers require that the full JID - of the sender be used. - :param mnick: Optional nickname of the sender. - """ - self.make_message(mto, mbody, msubject, mtype, - mhtml, mfrom, mnick).send() - - def send_presence(self, pshow=None, pstatus=None, ppriority=None, - pto=None, pfrom=None, ptype=None, pnick=None): - """ - Create, initialize, and send a new - :class:`~sleekxmpp.stanza.presence.Presence` stanza. - - :param pshow: The presence's show value. - :param pstatus: The presence's status message. - :param ppriority: This connection's priority. - :param pto: The recipient of a directed presence. - :param ptype: The type of presence, such as ``'subscribe'``. - :param pfrom: The sender of the presence. - :param pnick: Optional nickname of the presence's sender. - """ - self.make_presence(pshow, pstatus, ppriority, pto, - ptype, pfrom, pnick).send() - - def send_presence_subscription(self, pto, pfrom=None, - ptype='subscribe', pnick=None): - """ - Create, initialize, and send a new - :class:`~sleekxmpp.stanza.presence.Presence` stanza of - type ``'subscribe'``. - - :param pto: The recipient of a directed presence. - :param pfrom: The sender of the presence. - :param ptype: The type of presence, such as ``'subscribe'``. - :param pnick: Optional nickname of the presence's sender. - """ - self.make_presence(ptype=ptype, - pfrom=pfrom, - pto=JID(pto).bare, - pnick=pnick).send() - - @property - def jid(self): - """Attribute accessor for bare jid""" - log.warning("jid property deprecated. Use boundjid.bare") - return self.boundjid.bare - - @jid.setter - def jid(self, value): - log.warning("jid property deprecated. Use boundjid.bare") - self.boundjid.bare = value - - @property - def fulljid(self): - """Attribute accessor for full jid""" - log.warning("fulljid property deprecated. Use boundjid.full") - return self.boundjid.full - - @fulljid.setter - def fulljid(self, value): - log.warning("fulljid property deprecated. Use boundjid.full") - self.boundjid.full = value - - @property - def resource(self): - """Attribute accessor for jid resource""" - log.warning("resource property deprecated. Use boundjid.resource") - return self.boundjid.resource - - @resource.setter - def resource(self, value): - log.warning("fulljid property deprecated. Use boundjid.resource") - self.boundjid.resource = value - - @property - def username(self): - """Attribute accessor for jid usernode""" - log.warning("username property deprecated. Use boundjid.user") - return self.boundjid.user - - @username.setter - def username(self, value): - log.warning("username property deprecated. Use boundjid.user") - self.boundjid.user = value - - @property - def server(self): - """Attribute accessor for jid host""" - log.warning("server property deprecated. Use boundjid.host") - return self.boundjid.server - - @server.setter - def server(self, value): - log.warning("server property deprecated. Use boundjid.host") - self.boundjid.server = value - - @property - def auto_authorize(self): - """Auto accept or deny subscription requests. - - If ``True``, auto accept subscription requests. - If ``False``, auto deny subscription requests. - If ``None``, don't automatically respond. - """ - return self.roster.auto_authorize - - @auto_authorize.setter - def auto_authorize(self, value): - self.roster.auto_authorize = value - - @property - def auto_subscribe(self): - """Auto send requests for mutual subscriptions. - - If ``True``, auto send mutual subscription requests. - """ - return self.roster.auto_subscribe - - @auto_subscribe.setter - def auto_subscribe(self, value): - self.roster.auto_subscribe = value - - def set_jid(self, jid): - """Rip a JID apart and claim it as our own.""" - log.debug("setting jid to %s", jid) - self.boundjid = JID(jid, cache_lock=True) - - def getjidresource(self, fulljid): - if '/' in fulljid: - return fulljid.split('/', 1)[-1] - else: - return '' - - def getjidbare(self, fulljid): - return fulljid.split('/', 1)[0] - - def _handle_session_start(self, event): - """Reset redirection attempt count.""" - self._redirect_attempts = 0 - - def _handle_disconnected(self, event): - """When disconnected, reset the roster""" - self.roster.reset() - self.session_bind_event.clear() - - def _handle_stream_error(self, error): - self.event('stream_error', error) - - if error['condition'] == 'see-other-host': - other_host = error['see_other_host'] - if not other_host: - log.warning("No other host specified.") - return - - if self._redirect_attempts > self.max_redirects: - log.error("Exceeded maximum number of redirection attempts.") - return - - self._redirect_attempts += 1 - - host = other_host - port = 5222 - - if '[' in other_host and ']' in other_host: - host = other_host.split(']')[0][1:] - elif ':' in other_host: - host = other_host.split(':')[0] - - port_sec = other_host.split(']')[-1] - if ':' in port_sec: - port = int(port_sec.split(':')[1]) - - self.address = (host, port) - self.default_domain = host - self.dns_records = None - self.reconnect_delay = None - self.reconnect() - - def _handle_message(self, msg): - """Process incoming message stanzas.""" - if not self.is_component and not msg['to'].bare: - msg['to'] = self.boundjid - self.event('message', msg) - - def _handle_available(self, pres): - self.roster[pres['to']][pres['from']].handle_available(pres) - - def _handle_unavailable(self, pres): - self.roster[pres['to']][pres['from']].handle_unavailable(pres) - - def _handle_new_subscription(self, pres): - """Attempt to automatically handle subscription requests. - - Subscriptions will be approved if the request is from - a whitelisted JID, of :attr:`auto_authorize` is True. They - will be rejected if :attr:`auto_authorize` is False. Setting - :attr:`auto_authorize` to ``None`` will disable automatic - subscription handling (except for whitelisted JIDs). - - If a subscription is accepted, a request for a mutual - subscription will be sent if :attr:`auto_subscribe` is ``True``. - """ - roster = self.roster[pres['to']] - item = self.roster[pres['to']][pres['from']] - if item['whitelisted']: - item.authorize() - if roster.auto_subscribe: - item.subscribe() - elif roster.auto_authorize: - item.authorize() - if roster.auto_subscribe: - item.subscribe() - elif roster.auto_authorize == False: - item.unauthorize() - - def _handle_removed_subscription(self, pres): - self.roster[pres['to']][pres['from']].handle_unauthorize(pres) - - def _handle_subscribe(self, pres): - self.roster[pres['to']][pres['from']].handle_subscribe(pres) - - def _handle_subscribed(self, pres): - self.roster[pres['to']][pres['from']].handle_subscribed(pres) - - def _handle_unsubscribe(self, pres): - self.roster[pres['to']][pres['from']].handle_unsubscribe(pres) - - def _handle_unsubscribed(self, pres): - self.roster[pres['to']][pres['from']].handle_unsubscribed(pres) - - def _handle_presence(self, presence): - """Process incoming presence stanzas. - - Update the roster with presence information. - """ - if not self.is_component and not presence['to'].bare: - presence['to'] = self.boundjid - - self.event('presence', presence) - self.event('presence_%s' % presence['type'], presence) - - # Check for changes in subscription state. - if presence['type'] in ('subscribe', 'subscribed', - 'unsubscribe', 'unsubscribed'): - self.event('changed_subscription', presence) - return - elif not presence['type'] in ('available', 'unavailable') and \ - not presence['type'] in presence.showtypes: - return - - def exception(self, exception): - """Process any uncaught exceptions, notably - :class:`~sleekxmpp.exceptions.IqError` and - :class:`~sleekxmpp.exceptions.IqTimeout` exceptions. - - :param exception: An unhandled :class:`Exception` object. - """ - if isinstance(exception, IqError): - iq = exception.iq - log.error('%s: %s', iq['error']['condition'], - iq['error']['text']) - log.warning('You should catch IqError exceptions') - elif isinstance(exception, IqTimeout): - iq = exception.iq - log.error('Request timed out: %s', iq) - log.warning('You should catch IqTimeout exceptions') - elif isinstance(exception, SyntaxError): - # Hide stream parsing errors that occur when the - # stream is disconnected (they've been handled, we - # don't need to make a mess in the logs). - pass - else: - log.exception(exception) - - -# Restore the old, lowercased name for backwards compatibility. -basexmpp = BaseXMPP - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -BaseXMPP.registerPlugin = BaseXMPP.register_plugin -BaseXMPP.makeIq = BaseXMPP.make_iq -BaseXMPP.makeIqGet = BaseXMPP.make_iq_get -BaseXMPP.makeIqResult = BaseXMPP.make_iq_result -BaseXMPP.makeIqSet = BaseXMPP.make_iq_set -BaseXMPP.makeIqError = BaseXMPP.make_iq_error -BaseXMPP.makeIqQuery = BaseXMPP.make_iq_query -BaseXMPP.makeQueryRoster = BaseXMPP.make_query_roster -BaseXMPP.makeMessage = BaseXMPP.make_message -BaseXMPP.makePresence = BaseXMPP.make_presence -BaseXMPP.sendMessage = BaseXMPP.send_message -BaseXMPP.sendPresence = BaseXMPP.send_presence -BaseXMPP.sendPresenceSubscription = BaseXMPP.send_presence_subscription |