From 60dbc27b44ce2dcece55c87cf83c42e495a2e478 Mon Sep 17 00:00:00 2001 From: Marcel Jira Date: Mon, 19 Feb 2018 23:55:10 +0000 Subject: [PATCH 1/2] re-throw BrokenPipeError as mpd.ConnectionError --- doc/changes.rst | 2 ++ mpd/base.py | 20 ++++++++++++++++++-- mpd/tests.py | 12 ++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/doc/changes.rst b/doc/changes.rst index fd9db20..348e784 100644 --- a/doc/changes.rst +++ b/doc/changes.rst @@ -11,6 +11,8 @@ Changes in v0.6.0 (unreleased) * Introduce MPDClientBase class which provides common MPD communication related helpers. Used as base for synchronous and asynchronous clients * port argument is optional when connecting via unix sockets +* python-mpd will now raise mpd.ConnectionError instead of socket.error, when + connection is lost Changes in v0.5.5 diff --git a/mpd/base.py b/mpd/base.py index 50299fa..737d0fb 100644 --- a/mpd/base.py +++ b/mpd/base.py @@ -463,8 +463,24 @@ def _execute(self, command, args, retval): return retval def _write_line(self, line): - self._wfile.write("{}\n".format(line)) - self._wfile.flush() + try: + self._wfile.write("{}\n".format(line)) + self._wfile.flush() + except socket.error as e: + error_message = "Connection to server was reset" + logger.info(error_message) + self._reset() + if IS_PYTHON2: + # 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]') + else: + e = ConnectionError(error_message) + raise e.with_traceback(sys.exc_info()[2]) def _write_command(self, command, args=[]): parts = [command] diff --git a/mpd/tests.py b/mpd/tests.py index 9c716a3..f54a6c9 100755 --- a/mpd/tests.py +++ b/mpd/tests.py @@ -345,16 +345,28 @@ def test_set_timeout_from_connect(self): self.assertEqual(len(w), 1) self.assertIn('Use MPDClient.timeout', str(w[0].message)) + @unittest.skipIf(sys.version_info < (3, 3), "BrokenPipeError was introduced in python 3.3") + def test_broken_pipe_error(self): + self.MPDWillReturn('volume: 63\n', 'OK\n') + self.client._wfile.write.side_effect = BrokenPipeError + self.socket_mock.error = Exception + + with self.assertRaises(mpd.ConnectionError): + self.client.status() + def test_connection_lost(self): # Simulate a connection lost: the socket returns empty strings self.MPDWillReturn('') + self.socket_mock.error = Exception with self.assertRaises(mpd.ConnectionError): self.client.status() + self.socket_mock.unpack.assert_called() # consistent behaviour, solves bug #11 (github) with self.assertRaises(mpd.ConnectionError): self.client.status() + self.socket_mock.unpack.assert_called() self.assertIs(self.client._sock, None) From edfe2ad13e023fccf73807a98a5ca7f0b82f0eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 20 Feb 2018 00:10:22 +0000 Subject: [PATCH 2/2] Remove python3.6-dev --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e64692d..17ecfc7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ python: - "3.4" - "3.5" - "3.6" - - "3.6-dev" - "3.7-dev" - "nightly" - "pypy"