bpd: support ranges in playlistid

This commit is contained in:
Carl Suster 2019-04-13 15:28:53 +10:00
parent dc7e3b9b6a
commit d8be83bc0d
2 changed files with 31 additions and 10 deletions

View file

@ -583,23 +583,25 @@ class BaseServer(object):
"""Indicates supported URL schemes. None by default."""
pass
def cmd_playlistinfo(self, conn, index=-1):
def cmd_playlistinfo(self, conn, index=None):
"""Gives metadata information about the entire playlist or a
single track, given by its index.
"""
index = cast_arg(int, index)
if index == -1:
if index is None:
for track in self.playlist:
yield self._item_info(track)
else:
indices = self._parse_range(index, accept_single_number=True)
try:
track = self.playlist[index]
tracks = [self.playlist[i] for i in indices]
except IndexError:
raise ArgumentIndexError()
yield self._item_info(track)
for track in tracks:
yield self._item_info(track)
def cmd_playlistid(self, conn, track_id=-1):
if track_id != -1:
def cmd_playlistid(self, conn, track_id=None):
if track_id is not None:
track_id = cast_arg(int, track_id)
track_id = self._id_to_index(track_id)
return self.cmd_playlistinfo(conn, track_id)
@ -1139,6 +1141,21 @@ class Server(BaseServer):
return info_lines
def _parse_range(self, items, accept_single_number=False):
"""Convert a range of positions to a list of item info.
MPD specifies ranges as START:STOP (endpoint excluded) for some
commands. Sometimes a single number can be provided instead.
"""
try:
start, stop = str(items).split(':', 1)
except ValueError:
if accept_single_number:
return [cast_arg(int, items)]
raise BPDError(ERROR_ARG, u'bad range syntax')
start = cast_arg(int, start)
stop = cast_arg(int, stop)
return range(start, stop)
def _item_id(self, item):
return item.id

View file

@ -339,8 +339,9 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
previous_commands = response[0:pos]
self._assert_ok(*previous_commands)
response = response[pos]
self.assertEqual(pos, response.err_data[1])
self.assertFalse(response.ok)
if pos is not None:
self.assertEqual(pos, response.err_data[1])
if code is not None:
self.assertEqual(code, response.err_data[0])
@ -781,12 +782,15 @@ class BPDQueueTest(BPDTestHelper):
def test_cmd_playlistinfo(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1)
self._bpd_add(client, self.item1, self.item2)
responses = client.send_commands(
('playlistinfo',),
('playlistinfo', '0'),
('playlistinfo', '0:2'),
('playlistinfo', '200'))
self._assert_failed(responses, bpd.ERROR_ARG, pos=2)
self._assert_failed(responses, bpd.ERROR_ARG, pos=3)
self.assertEqual('1', responses[1].data['Id'])
self.assertEqual(['1', '2'], responses[2].data['Id'])
def test_cmd_playlistinfo_tagtypes(self):
with self.run_bpd() as client: