From 71e7621642fa996e6c4b0eff8e5ad1afa58a3ca8 Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Mon, 1 Apr 2019 11:28:31 +1100 Subject: [PATCH] bpd: no-op support for persistent playlists The real MPD offers persistent playlist manipulation, storing the playlists in a directory set in the config file. If that directory is not available then the feature is disabled and the relevant commands all respond with errors. Based on this, the initial support in bpd just returns errors matching the MPD server in the disabled mode. For playlistadd, extend the _bpd_add helper to work with playlists other than the queue in order to support testing the real implementations of these commands in the future. --- beetsplug/bpd/__init__.py | 36 +++++++++++++++++++ test/test_player.py | 74 ++++++++++++++++++++++++++++++++++----- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index a0d6d6254..c29b0604d 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -1136,6 +1136,42 @@ class Server(BaseServer): yield u'songs: ' + six.text_type(songs) yield u'playtime: ' + six.text_type(int(playtime)) + # Persistent playlist manipulation. In MPD this is an optional feature so + # these dummy implementations match MPD's behaviour with the feature off. + + def cmd_listplaylist(self, conn, playlist): + raise BPDError(ERROR_NO_EXIST, u'No such playlist') + + def cmd_listplaylistinfo(self, conn, playlist): + raise BPDError(ERROR_NO_EXIST, u'No such playlist') + + def cmd_listplaylists(self, conn): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_load(self, conn, playlist): + raise BPDError(ERROR_NO_EXIST, u'Stored playlists are disabled') + + def cmd_playlistadd(self, conn, playlist, uri): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_playlistclear(self, conn, playlist): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_playlistdelete(self, conn, playlist, index): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_playlistmove(self, conn, playlist, from_index, to_index): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_rename(self, conn, playlist, new_name): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_rm(self, conn, playlist): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + + def cmd_save(self, conn, playlist): + raise BPDError(ERROR_UNKNOWN, u'Stored playlists are disabled') + # "Outputs." Just a dummy implementation because we don't control # any outputs. diff --git a/test/test_player.py b/test/test_player.py index b9544769c..80ba595cd 100644 --- a/test/test_player.py +++ b/test/test_player.py @@ -327,13 +327,18 @@ class BPDTestHelper(unittest.TestCase, TestHelper): if code is not None: self.assertEqual(code, response.err_data[0]) - def _bpd_add(self, client, *items): - """ Add the given item to the BPD playlist + def _bpd_add(self, client, *items, **kwargs): + """ Add the given item to the BPD playlist or queue. """ paths = ['/'.join([ item.artist, item.album, py3_path(os.path.basename(item.path))]) for item in items] - responses = client.send_commands(*[('add', path) for path in paths]) + playlist = kwargs.get('playlist') + if playlist: + commands = [('playlistadd', playlist, path) for path in paths] + else: + commands = [('add', path) for path in paths] + responses = client.send_commands(*commands) self._assert_ok(*responses) @@ -488,11 +493,64 @@ class BPDQueueTest(BPDTestHelper): class BPDPlaylistsTest(BPDTestHelper): - test_implements_playlists = implements({ - 'listplaylist', 'listplaylistinfo', 'listplaylists', 'load', - 'playlistadd', 'playlistclear', 'playlistdelete', - 'playlistmove', 'rename', 'rm', 'save', - }, expectedFailure=True) + test_implements_playlists = implements({'playlistadd'}) + + def test_cmd_listplaylist(self): + with self.run_bpd() as client: + response = client.send_command('listplaylist', 'anything') + self._assert_failed(response, bpd.ERROR_NO_EXIST) + + def test_cmd_listplaylistinfo(self): + with self.run_bpd() as client: + response = client.send_command('listplaylistinfo', 'anything') + self._assert_failed(response, bpd.ERROR_NO_EXIST) + + def test_cmd_listplaylists(self): + with self.run_bpd() as client: + response = client.send_command('listplaylists') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_load(self): + with self.run_bpd() as client: + response = client.send_command('load', 'anything') + self._assert_failed(response, bpd.ERROR_NO_EXIST) + + @unittest.skip + def test_cmd_playlistadd(self): + with self.run_bpd() as client: + self._bpd_add(client, self.item1, playlist='anything') + + def test_cmd_playlistclear(self): + with self.run_bpd() as client: + response = client.send_command('playlistclear', 'anything') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_playlistdelete(self): + with self.run_bpd() as client: + response = client.send_command('playlistdelete', 'anything', '0') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_playlistmove(self): + with self.run_bpd() as client: + response = client.send_command( + 'playlistmove', 'anything', '0', '1') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_rename(self): + with self.run_bpd() as client: + response = client.send_command('rename', 'anything', 'newname') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_rm(self): + with self.run_bpd() as client: + response = client.send_command('rm', 'anything') + self._assert_failed(response, bpd.ERROR_UNKNOWN) + + def test_cmd_save(self): + with self.run_bpd() as client: + self._bpd_add(client, self.item1) + response = client.send_command('save', 'newplaylist') + self._assert_failed(response, bpd.ERROR_UNKNOWN) class BPDDatabaseTest(BPDTestHelper):