Source code for pushjack.exceptions

# -*- coding: utf-8 -*-
"""Exceptions module.
"""

from ._compat import iteritems


__all__ = (
    'APNSError',
    'APNSAuthError',
    'APNSServerError',
    'APNSProcessingError',
    'APNSMissingTokenError',
    'APNSMissingTopicError',
    'APNSMissingPayloadError',
    'APNSInvalidTokenSizeError',
    'APNSInvalidTopicSizeError',
    'APNSInvalidPayloadSizeError',
    'APNSInvalidTokenError',
    'APNSShutdownError',
    'APNSProtocolError',
    'APNSUnknownError',
    'APNSTimeoutError',
    'APNSUnsendableError',
    'GCMError',
    'GCMAuthError',
    'GCMServerError',
    'GCMMissingRegistrationError',
    'GCMInvalidRegistrationError',
    'GCMUnregisteredDeviceError',
    'GCMInvalidPackageNameError',
    'GCMMismatchedSenderError',
    'GCMMessageTooBigError',
    'GCMInvalidDataKeyError',
    'GCMInvalidTimeToLiveError',
    'GCMTimeoutError',
    'GCMInternalServerError',
    'GCMDeviceMessageRateExceededError',
    'NotificationError',
    'ServerError',
)


class NotificationError(Exception):
    """Base exception for all notification errors."""
    code = None
    description = None
    fatal = False


class ServerError(NotificationError):
    """Base exception for server errors."""
    def __init__(self, identifier):
        super(ServerError, self).__init__(self.code,
                                          self.description,
                                          identifier)
        self.identifier = identifier

    def __str__(self):  # pragma: no cover
        return '{0} (code={1}): {2} for identifier {3}'.format(
            self.__class__.__name__,
            self.code,
            self.description,
            self.identifier)

    def __repr__(self):  # pragma: no cover
        return str(self)


[docs]class APNSError(NotificationError): """Base exception for APNS errors.""" pass
[docs]class APNSAuthError(APNSError): """Exception with APNS certificate.""" pass
[docs]class APNSServerError(ServerError): """Base exception for APNS Server errors.""" pass
[docs]class APNSProcessingError(APNSServerError): """Exception for APNS processing error.""" code = 1 description = 'Processing error'
[docs]class APNSMissingTokenError(APNSServerError): """Exception for APNS missing token error.""" code = 2 description = 'Missing token'
[docs]class APNSMissingTopicError(APNSServerError): """Exception for APNS missing topic error.""" code = 3 description = 'Missing topic' fatal = True
[docs]class APNSMissingPayloadError(APNSServerError): """Exception for APNS payload error.""" code = 4 description = 'Missing payload' fatal = True
[docs]class APNSInvalidTokenSizeError(APNSServerError): """Exception for APNS invalid token size error.""" code = 5 description = 'Invalid token size'
[docs]class APNSInvalidTopicSizeError(APNSServerError): """Exception for APNS invalid topic size error.""" code = 6 description = 'Invalid topic size' fatal = True
[docs]class APNSInvalidPayloadSizeError(APNSServerError): """Exception for APNS invalid payload size error.""" code = 7 description = 'Invalid payload size' fatal = True
[docs]class APNSInvalidTokenError(APNSServerError): """Exception for APNS invalid token error.""" code = 8 description = 'Invalid token'
[docs]class APNSShutdownError(APNSServerError): """Exception for APNS shutdown error.""" code = 10 description = 'Shutdown'
class APNSProtocolError(APNSServerError): """Exception for APNS protocol error.""" code = 128 description = 'Protocol'
[docs]class APNSUnknownError(APNSServerError): """Exception for APNS unknown error.""" code = 255 description = 'Unknown'
class APNSTimeoutError(APNSServerError): """Exception for APNS connection timeout error.""" description = 'Timeout' fatal = True class APNSUnsendableError(APNSServerError): """Exception for when notification can't be send due to previous error for another notification. """ description = 'Unable to send due to previous error'
[docs]class GCMError(NotificationError): """Base exception for GCM errors.""" pass
[docs]class GCMAuthError(GCMError): """Exception for error with GCM API key.""" pass
[docs]class GCMServerError(ServerError): """Base exception for GCM Server errors.""" pass
[docs]class GCMMissingRegistrationError(GCMServerError): """Exception for missing registration ID.""" code = 'MissingRegistration' description = 'Missing registration ID'
[docs]class GCMInvalidRegistrationError(GCMServerError): """Exception for invalid registration ID""" code = 'InvalidRegistration' description = 'Invalid registration ID'
[docs]class GCMUnregisteredDeviceError(GCMServerError): """Exception for unregistered device.""" code = 'NotRegistered' description = 'Device not registered'
[docs]class GCMInvalidPackageNameError(GCMServerError): """Exception for invalid package name.""" code = 'InvalidPackageName' description = 'Invalid package name'
[docs]class GCMMismatchedSenderError(GCMServerError): """Exception for mismatched sender.""" code = 'MismatchSenderId' description = 'Mismatched sender ID'
[docs]class GCMMessageTooBigError(GCMServerError): """Exception for message too big.""" code = 'MessageTooBig' description = 'Message too big'
[docs]class GCMInvalidDataKeyError(GCMServerError): """Exception for invalid data key.""" code = 'InvalidDataKey' description = 'Invalid data key'
[docs]class GCMInvalidTimeToLiveError(GCMServerError): """Exception for invalid time to live.""" code = 'InvalidTtl' description = 'Invalid time to live'
[docs]class GCMTimeoutError(GCMServerError): """Exception for server timeout.""" code = 'Unavailable' description = 'Timeout'
[docs]class GCMInternalServerError(GCMServerError): """Exception for internal server error.""" code = 'InternalServerError' description = 'Internal server error'
[docs]class GCMDeviceMessageRateExceededError(GCMServerError): """Exception for device message rate exceeded.""" code = 'DeviceMessageRateExceeded' description = 'Device message rate exceeded'
class Raiser(object): """Helper class for raising an exception based on error class name prefix and exception code. """ prefix = None fallback_exception = None def __init__(self, mapping): self.mapping = mapping def __call__(self, code, identifier): if code not in self.mapping: # pragma: no cover # pylint: disable=not-callable raise self.fallback_exception(identifier) raise self.mapping[code](identifier) class APNSServerRasier(Raiser): """Exception raiser class for APNS errors.""" prefix = 'APNS' fallback_exception = APNSUnknownError class GCMServerRaiser(Raiser): """Exception raiser classs for GCM server errors.""" prefix = 'GCM' fallback_exception = GCMServerError def map_errors(prefix): mapping = {} for name, obj in iteritems(globals()): if (name.startswith(prefix) and getattr(obj, 'code', None) is not None): mapping[obj.code] = obj return mapping apns_server_errors = map_errors('APNS') gcm_server_errors = map_errors('GCM') #: Helper method to raise GCM server errors. raise_gcm_server_error = GCMServerRaiser(gcm_server_errors) #: Helper method to raise APNS server errors. raise_apns_server_error = APNSServerRasier(apns_server_errors)