Skip to content
67 changes: 66 additions & 1 deletion mpd.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
SUCCESS = "OK"
NEXT = "list_OK"

IS_BELOW_PYTHON3_3 = sys.version_info < (3, 3)
IS_PYTHON2 = sys.version_info < (3, 0)
if IS_PYTHON2:
def decode_str(s):
Expand Down Expand Up @@ -254,10 +255,74 @@ def _execute(self, command, args, retval):
return retval()
return retval

def _write_line(self, line):
def _write_line_actions(self, line):
self._wfile.write("%s\n" % line)
self._wfile.flush()

def _write_line(self, line):
error_message = "Connection to server was reset"

try:
self._write_line_actions(line)
except socket.error as e:
logger.info(error_message)
self._reset()
if IS_PYTHON2:
self._raise_connection_error_python2(error_message)
else:
self._raise_connection_error_python3(error_message)

# The below/above Python 3.3 switch is not necessary at the moment, as
# socket.error is an alias of OSError in Python >= 3.3. However,
# socket.error is deprecated in Python >= 3.3, so it could possibly be
# removed in the future. For this (unlike) event, the code above can
# be removed and the switch can be uncommented again.
# if IS_BELOW_PYTHON3_3:
# self._write_line_below_python3_3(line, error_message)
# else:
# self._write_line_from_python3_3(line, error_message)
#
# def _write_line_below_python3_3(self, line, error_message):
# try:
# self._write_line_actions(line)
# # catch broken pipe in Python3.2 and below (appears as socket.error)
# # note that a socket.error in Python >= 3.3 is an alias of OSError
# # so it's necessary to seperate Python <3.3 and Python >=3.3 (otherwise
# # Python 3.3 would also try to handle this exception (BrokenPipeError
# # is a subclass of OSError)
# # https://docs.python.org/3/library/socket.html#socket.error
# except socket.error as e:
# logger.info(error_message)
# self._reset()
# if IS_PYTHON2:
# self._raise_connection_error_python2(error_message)
# else:
# self._raise_connection_error_python3(error_message)
#
# def _write_line_from_python3_3(self, line, error_message):
# try:
# self._write_line_actions(line)
# # catch broken pipe in Python3.3 and above (appears as BrokenPipeError)
# # https://docs.python.org/3/library/exceptions.html#BrokenPipeError
# # BrokenPipeError inherits from OSError, which is caught here
# except OSError as e:
# logger.info(error_message)
# self._reset()
# self._raise_connection_error_python3(error_message)

def _raise_connection_error_python2(self, error_message):
# Utilizing exec is not particularly elegant, however, it seems to
# be the only way as Python3 handles exceptions quite different to
# Python2. Without exec, the whole script is not executable in
# Python3. Also "six" does it the same way:
# https://bitbucket.org/gutworth/six/src/ (search "reraise")
exec('raise ConnectionError, "' + error_message + '",'
'sys.exc_info()[2]')

def _raise_connection_error_python3(self, error_message):
raise (ConnectionError(error_message)
.with_traceback(sys.exc_info()[2]))

def _write_command(self, command, args=[]):
parts = [command]
for arg in args:
Expand Down