Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# -*- coding: utf-8 -*-
# Disable while we have Python 2.x compatability
# pylint: disable=useless-object-inheritance
"""Exceptions that are used by SoCo."""
from __future__ import unicode_literals
class SoCoException(Exception):
"""Base class for all SoCo exceptions."""
class UnknownSoCoException(SoCoException):
"""An unknown UPnP error.
The exception object will contain the raw response sent back from
the speaker as the first of its args.
"""
class SoCoUPnPException(SoCoException):
"""A UPnP Fault Code, raised in response to actions sent over the
network.
"""
def __init__(self, message, error_code, error_xml, error_description=""):
`CannotCreateDIDLMetadata`. In a future version, it will likely become
a direct subclass of `SoCoException`.
"""
class MusicServiceException(SoCoException):
"""An error relating to a third party music service."""
class UnknownXMLStructure(SoCoException):
"""Raised if XML with an unknown or unexpected structure is returned."""
class SoCoSlaveException(SoCoException):
"""Raised when a master command is called on a slave."""
class NotSupportedException(SoCoException):
"""Raised when something is not supported by the device"""
class EventParseException(SoCoException):
"""Raised when a parsing exception occurs during event handling.
Attributes:
tag (str): The tag for which the exception occured
metadata (str): The metadata which failed to parse
__cause__ (Exception): The original exception
"""
# subscriptions are auto-renewed. Be careful to ensure thread-safety
if is_autorenew:
log_msg = "Autorenewing subscription %s"
else:
log_msg = "Renewing subscription %s"
log.info(log_msg, self.sid)
if self._has_been_unsubscribed:
raise SoCoException(
"Cannot renew subscription once unsubscribed")
if not self.is_subscribed:
raise SoCoException(
"Cannot renew subscription before subscribing")
if self.time_left == 0:
raise SoCoException(
"Cannot renew subscription after expiry")
# SUBSCRIBE publisher path HTTP/1.1
# HOST: publisher host:publisher port
# SID: uuid:subscription UUID
# TIMEOUT: Second-requested subscription duration (optional)
headers = {
'SID': self.sid
}
if requested_timeout is None:
requested_timeout = self.requested_timeout
if requested_timeout is not None:
headers["TIMEOUT"] = "Second-{}".format(requested_timeout)
# pylint: disable=missing-docstring
def success(headers):
def handle_outcome(outcome):
"""A callback / errback to handle the outcome ofmethod,
after it has been executed
"""
# We start by assuming no Failure occurred
failure = None
if isinstance(outcome, Failure):
failure = outcome
# If a Failure or Exception occurred during execution of
# subscribe, renew or unsubscribe, cancel it unless the
# Failure or Exception was a SoCoException upon subscribe
if failure.type != SoCoException or action == 'renew':
msg = "An Exception occurred. Subscription to" +\
" {}, sid: {} has been cancelled".format(
self.service.base_url +
self.service.event_subscription_url,
self.sid)
self._cancel_subscription(msg)
# If we're not being strict, log the Failure
if not strict:
msg = "Failure received in Subscription" +\
".{} for Subscription to:\n{}, sid: {}: {}".format(
action,
self.service.base_url +
self.service.event_subscription_url,
self.sid,
str(failure))
log.exception(msg)
class UnknownXMLStructure(SoCoException):
"""Raised if XML with an unknown or unexpected structure is returned."""
class SoCoSlaveException(SoCoException):
"""Raised when a master command is called on a slave."""
class NotSupportedException(SoCoException):
"""Raised when something is not supported by the device"""
class EventParseException(SoCoException):
"""Raised when a parsing exception occurs during event handling.
Attributes:
tag (str): The tag for which the exception occured
metadata (str): The metadata which failed to parse
__cause__ (Exception): The original exception
"""
def __init__(self, tag, metadata, cause):
"""
Args:
tag (str): The tag for which the exception occured
metadata (str): The metadata which failed to parse
cause (Exception): The original exception
"""
super(EventParseException, self).__init__()
requested_timeout(int, optional): The timeout to be requested.
auto_renew (bool, optional): If `True`, renew the subscription
automatically shortly before timeout. Default `False`.
"""
# TIMEOUT is provided for in the UPnP spec, but it is not clear if
# Sonos pays any attention to it. A timeout of 86400 secs always seems
# to be allocated
self.requested_timeout = requested_timeout
if self.is_subscribed:
raise SoCoException(
'Cannot subscribe Subscription instance more than once. ' +
'Use renew instead')
if self._has_been_unsubscribed:
raise SoCoException(
'Cannot resubscribe Subscription instance once unsubscribed')
service = self.service
# The Event Listener must be running, so start it if not
# pylint: disable=no-member
if not self.event_listener.is_running:
self.event_listener.start(service.soco)
# an event subscription looks like this:
# SUBSCRIBE publisher path HTTP/1.1
# HOST: publisher host:publisher port
# CALLBACK:
# NT: upnp:event
# TIMEOUT: Second-requested subscription duration (optional)
# pylint: disable=unbalanced-tuple-unpacking
ip_address, port = self.event_listener.address
"""Raised if a data container class cannot create the DIDL metadata due to
missing information.
For backward compatibility, this is currently a subclass of
`CannotCreateDIDLMetadata`. In a future version, it will likely become
a direct subclass of `SoCoException`.
"""
class MusicServiceException(SoCoException):
"""An error relating to a third party music service."""
class UnknownXMLStructure(SoCoException):
"""Raised if XML with an unknown or unexpected structure is returned."""
class SoCoSlaveException(SoCoException):
"""Raised when a master command is called on a slave."""
class NotSupportedException(SoCoException):
"""Raised when something is not supported by the device"""
class EventParseException(SoCoException):
"""Raised when a parsing exception occurs during event handling.
Attributes:
request should be made. If None (the default), use the timeout
requested on subscription.
is_autorenew (bool, optional): Whether this is an autorenewal.
"""
# NB This code may be called from a separate thread when
# subscriptions are auto-renewed. Be careful to ensure thread-safety
if is_autorenew:
log_msg = "Autorenewing subscription %s"
else:
log_msg = "Renewing subscription %s"
log.info(log_msg, self.sid)
if self._has_been_unsubscribed:
raise SoCoException(
"Cannot renew subscription once unsubscribed")
if not self.is_subscribed:
raise SoCoException(
"Cannot renew subscription before subscribing")
if self.time_left == 0:
raise SoCoException(
"Cannot renew subscription after expiry")
# SUBSCRIBE publisher path HTTP/1.1
# HOST: publisher host:publisher port
# SID: uuid:subscription UUID
# TIMEOUT: Second-requested subscription duration (optional)
headers = {
'SID': self.sid
}
if requested_timeout is None:
error_code (str): The UPnP Error Code as a string.
error_xml (str): The xml containing the error, as a utf-8
encoded string.
error_description (str): A description of the error. Default is ""
"""
super(SoCoUPnPException, self).__init__()
self.message = message
self.error_code = error_code
self.error_description = error_description
self.error_xml = error_xml
def __str__(self):
return self.message
class CannotCreateDIDLMetadata(SoCoException):
"""
.. deprecated:: 0.11
Use `DIDLMetadataError` instead.
"""
class DIDLMetadataError(CannotCreateDIDLMetadata):
"""Raised if a data container class cannot create the DIDL metadata due to
missing information.
For backward compatibility, this is currently a subclass of
`CannotCreateDIDLMetadata`. In a future version, it will likely become
a direct subclass of `SoCoException`.
"""
class SoCoException(Exception):
"""Base class for all SoCo exceptions."""
class UnknownSoCoException(SoCoException):
"""An unknown UPnP error.
The exception object will contain the raw response sent back from
the speaker as the first of its args.
"""
class SoCoUPnPException(SoCoException):
"""A UPnP Fault Code, raised in response to actions sent over the
network.
"""
def __init__(self, message, error_code, error_xml, error_description=""):
"""
Args:
message (str): The message from the server.
error_code (str): The UPnP Error Code as a string.
error_xml (str): The xml containing the error, as a utf-8
encoded string.
error_description (str): A description of the error. Default is ""
"""
super(SoCoUPnPException, self).__init__()