Source code for aioxmpp.errors

"""
:mod:`~aioxmpp.errors` --- Exception classes
############################################

Exception classes mapping to XMPP stream errors
===============================================

.. autoclass:: StreamError

Exception classes mapping to XMPP stanza errors
===============================================

.. autoclass:: StanzaError

.. autoclass:: XMPPError

.. autoclass:: XMPPAuthError

.. autoclass:: XMPPModifyError

.. autoclass:: XMPPCancelError

.. autoclass:: XMPPWaitError

.. autoclass:: XMPPContinueError

.. autoclass:: ErroneousStanza

Stream negotiation exceptions
=============================

.. autoclass:: StreamNegotiationFailure

.. autoclass:: SecurityNegotiationFailure

.. autoclass:: SASLUnavailable

.. autoclass:: TLSFailure

.. autoclass:: TLSUnavailable

I18N exceptions
===============

.. autoclass:: UserError

.. autoclass:: UserValueError

Other exceptions
================

.. autoclass:: MultiOSError

"""
import gettext

import aiosasl

from . import xso, i18n


def format_error_text(
        condition,
        text=None,
        application_defined_condition=None):
    error_tag = xso.tag_to_str(condition)
    if application_defined_condition is not None:
        error_tag += "/{}".format(application_defined_condition.tag)
    if text:
        error_tag += " ({!r})".format(text)
    return error_tag


[docs]class StreamError(ConnectionError): def __init__(self, condition, text=None): super().__init__("stream error: {}".format( format_error_text(condition, text))) self.condition = condition self.text = text
[docs]class StanzaError(Exception): pass
[docs]class XMPPError(StanzaError): TYPE = "cancel" def __init__(self, condition, text=None, application_defined_condition=None): super().__init__(format_error_text( condition, text=text, application_defined_condition=application_defined_condition)) self.condition = condition self.text = text self.application_defined_condition = application_defined_condition
class XMPPWarning(XMPPError, UserWarning): TYPE = "continue"
[docs]class XMPPAuthError(XMPPError, PermissionError): TYPE = "auth"
[docs]class XMPPModifyError(XMPPError, ValueError): TYPE = "modify"
[docs]class XMPPCancelError(XMPPError): TYPE = "cancel"
[docs]class XMPPWaitError(XMPPError): TYPE = "wait"
[docs]class XMPPContinueError(XMPPWarning): TYPE = "continue"
[docs]class ErroneousStanza(StanzaError): """ This exception is thrown into listeners for IQ responses by :class:`aioxmpp.stream.StanzaStream` if a response for an IQ was received, but could not be decoded (due to malformed or unsupported payload). .. attribute:: partial_obj Contains the partially decoded stanza XSO. Do not rely on any members except those representing XML attributes (:attr:`~.StanzaBase.to`, :attr:`~.StanzaBase.from_`, :attr:`~.StanzaBase.type_`). """ def __init__(self, partial_obj): super().__init__("erroneous stanza received: {!r}".format( partial_obj)) self.partial_obj = partial_obj
[docs]class StreamNegotiationFailure(ConnectionError): pass
[docs]class SecurityNegotiationFailure(StreamNegotiationFailure): def __init__(self, xmpp_error, kind="Security negotiation failure", text=None): msg = "{}: {}".format(kind, xmpp_error) if text: msg += " ('{}')".format(text) super().__init__(msg) self.xmpp_error = xmpp_error self.text = text
[docs]class SASLUnavailable(SecurityNegotiationFailure): # we use this to tell the Client that SASL has not been available at all, # or that we could not agree on mechansims. # it might be helpful to notify the peer about this before dying. pass
[docs]class TLSFailure(SecurityNegotiationFailure): def __init__(self, xmpp_error, text=None): super().__init__(xmpp_error, text=text, kind="TLS failure")
[docs]class TLSUnavailable(TLSFailure): pass
error_type_map = { "auth": XMPPAuthError, "modify": XMPPModifyError, "cancel": XMPPCancelError, "wait": XMPPWaitError, "continue": XMPPContinueError, }
[docs]class UserError(Exception): """ An exception subclass, which should be used as a mix-in. It is intended to be used for exceptions which may be user-facing, such as connection errors, value validation issues and the like. `localizable_string` must be a :class:`.i18n.LocalizableString` instance. The `args` and `kwargs` will be passed to :class:`.LocalizableString.localize` when either :func:`str` is called on the :class:`UserError` or :meth:`localize` is called. The :func:`str` is created using the default :class:`~.i18n.LocalizingFormatter` and a :class:`gettext.NullTranslations` instance. The point in time at which the default localizing formatter is created is unspecified. .. automethod:: localize """ DEFAULT_FORMATTER = i18n.LocalizingFormatter() DEFAULT_TRANSLATIONS = gettext.NullTranslations() def __init__(self, localizable_string, *args, **kwargs): super().__init__() self._str = localizable_string.localize( self.DEFAULT_FORMATTER, self.DEFAULT_TRANSLATIONS, *args, **kwargs) self.localizable_string = localizable_string self.args = args self.kwargs = kwargs def __str__(self): return str(self._str)
[docs] def localize(self, formatter, translator): """ Return a localized version of the `localizable_string` passed to the consturctor. It is formatted using the `formatter` with the `args` and `kwargs` passed to the constructor of :class:`UserError`. """ return self.localizable_string.localize( formatter, translator, *self.args, **self.kwargs )
[docs]class UserValueError(UserError, ValueError): """ This is a :class:`ValueError` with :class:`UserError` mixed in. """
[docs]class MultiOSError(OSError): """ Describe an error situation which has been caused by the sequential occurence of multiple other `exceptions`. The `message` shall be descriptive and will be prepended to a concatenation of the error messages of the given `exceptions`. """ def __init__(self, message, exceptions): flattened_exceptions = [] for exc in exceptions: if hasattr(exc, "exceptions"): flattened_exceptions.extend(exc.exceptions) else: flattened_exceptions.append(exc) super().__init__( "{}: multiple errors: {}".format( message, ", ".join(map(str, flattened_exceptions)) ) ) self.exceptions = flattened_exceptions