mpd: Update tokenizer to use mopidy.mpd.exceptions

This commit is contained in:
Thomas Adamcik 2014-01-22 00:10:30 +01:00
parent 756cf1518b
commit 066fed1522
3 changed files with 56 additions and 40 deletions

View File

@ -54,9 +54,11 @@ class MpdPermissionError(MpdAckError):
self.message = 'you don\'t have permission for "%s"' % self.command
class MpdUnknownCommand(MpdAckError):
class MpdUnknownError(MpdAckError):
error_code = MpdAckError.ACK_ERROR_UNKNOWN
class MpdUnknownCommand(MpdUnknownError):
def __init__(self, *args, **kwargs):
super(MpdUnknownCommand, self).__init__(*args, **kwargs)
assert self.command is not None, 'command must be given explicitly'

View File

@ -2,6 +2,8 @@ from __future__ import unicode_literals
import re
from mopidy.mpd import exceptions
class Error(Exception):
pass
@ -42,27 +44,31 @@ UNESCAPE_RE = re.compile(r'\\(.)') # Backslash escapes any following char.
def split(line):
if not line.strip():
raise Error('No command given') # 5@0
raise exceptions.MpdNoCommand('No command given')
match = WORD_RE.match(line)
if not match:
raise Error('Invalid word character') # 5@0
raise exceptions.MpdUnknownError('Invalid word character')
whitespace, command, remainder = match.groups()
if whitespace:
raise Error('Letter expected') # 5@0
raise exceptions.MpdUnknownError('Letter expected')
result = [command]
while remainder:
match = PARAM_RE.match(remainder)
if not match:
# Following checks are simply to match MPD error messages:
match = BAD_QUOTED_PARAM_RE.match(remainder)
if match:
if match.group(1):
raise Error('Space expected after closing \'"\'') # 2@0
else:
raise Error('Missing closing \'"\'') # 2@0
raise Error('Invalid unquoted character') # 2@0
msg = _determine_error_message(remainder)
raise exceptions.MpdArgError(msg, command=command)
unquoted, quoted, remainder = match.groups()
result.append(unquoted or UNESCAPE_RE.sub(r'\g<1>', quoted))
return result
def _determine_error_message(remainder):
# Following checks are simply to match MPD error messages:
match = BAD_QUOTED_PARAM_RE.match(remainder)
if match:
if match.group(1):
return 'Space expected after closing \'"\''
else:
return 'Missing closing \'"\''
return 'Invalid unquoted character'

View File

@ -4,25 +4,24 @@ from __future__ import unicode_literals
import unittest
from mopidy.mpd import tokenize
from mopidy.mpd import exceptions, tokenize
class TestTokenizer(unittest.TestCase):
def assertTokenizeEquals(self, expected, line):
self.assertEqual(expected, tokenize.split(line))
def assertTokenizeRaisesError(self, line, message=None):
with self.assertRaises(tokenize.Error) as cm:
def assertTokenizeRaises(self, exception, message, line):
with self.assertRaises(exception) as cm:
tokenize.split(line)
if message:
self.assertEqual(cm.exception.message, message)
self.assertEqual(cm.exception.message, message)
def test_empty_string(self):
self.assertTokenizeRaisesError('', 'No command given')
def test_whitespace(self):
self.assertTokenizeRaisesError(' ', 'No command given')
self.assertTokenizeRaisesError('\t\t\t', 'No command given')
ex = exceptions.MpdNoCommand
msg = 'No command given'
self.assertTokenizeRaises(ex, msg, '')
self.assertTokenizeRaises(ex, msg, ' ')
self.assertTokenizeRaises(ex, msg, '\t\t\t')
def test_command(self):
self.assertTokenizeEquals(['test'], 'test')
@ -34,14 +33,18 @@ class TestTokenizer(unittest.TestCase):
self.assertTokenizeEquals(['test'], 'test\t\t\t')
def test_command_leading_whitespace(self):
self.assertTokenizeRaisesError(' test', 'Letter expected')
self.assertTokenizeRaisesError('\ttest', 'Letter expected')
ex = exceptions.MpdUnknownError
msg = 'Letter expected'
self.assertTokenizeRaises(ex, msg, ' test')
self.assertTokenizeRaises(ex, msg, '\ttest')
def test_invalid_command(self):
self.assertTokenizeRaisesError('foo/bar', 'Invalid word character')
self.assertTokenizeRaisesError('æøå', 'Invalid word character')
self.assertTokenizeRaisesError('test?', 'Invalid word character')
self.assertTokenizeRaisesError('te"st', 'Invalid word character')
ex = exceptions.MpdUnknownError
msg = 'Invalid word character'
self.assertTokenizeRaises(ex, msg, 'foo/bar')
self.assertTokenizeRaises(ex, msg, 'æøå')
self.assertTokenizeRaises(ex, msg, 'test?')
self.assertTokenizeRaises(ex, msg, 'te"st')
def test_unquoted_param(self):
self.assertTokenizeEquals(['test', 'param'], 'test param')
@ -56,11 +59,12 @@ class TestTokenizer(unittest.TestCase):
self.assertTokenizeEquals(['test', 'param'], 'test param\t\t')
def test_unquoted_param_invalid_chars(self):
ex = exceptions.MpdArgError
msg = 'Invalid unquoted character'
self.assertTokenizeRaisesError('test par"m', msg)
self.assertTokenizeRaisesError('test foo\bbar', msg)
self.assertTokenizeRaisesError('test foo"bar"baz', msg)
self.assertTokenizeRaisesError('test foo\'bar', msg)
self.assertTokenizeRaises(ex, msg, 'test par"m')
self.assertTokenizeRaises(ex, msg, 'test foo\bbar')
self.assertTokenizeRaises(ex, msg, 'test foo"bar"baz')
self.assertTokenizeRaises(ex, msg, 'test foo\'bar')
def test_unquoted_param_numbers(self):
self.assertTokenizeEquals(['test', '123'], 'test 123')
@ -90,11 +94,12 @@ class TestTokenizer(unittest.TestCase):
self.assertTokenizeEquals(['test', 'param'], 'test "param"\t\t')
def test_quoted_param_invalid_chars(self):
ex = exceptions.MpdArgError
msg = 'Space expected after closing \'"\''
self.assertTokenizeRaisesError('test "foo"bar"', msg)
self.assertTokenizeRaisesError('test "foo"bar" ', msg)
self.assertTokenizeRaisesError('test "foo"bar', msg)
self.assertTokenizeRaisesError('test "foo"bar ', msg)
self.assertTokenizeRaises(ex, msg, 'test "foo"bar"')
self.assertTokenizeRaises(ex, msg, 'test "foo"bar" ')
self.assertTokenizeRaises(ex, msg, 'test "foo"bar')
self.assertTokenizeRaises(ex, msg, 'test "foo"bar ')
def test_quoted_param_numbers(self):
self.assertTokenizeEquals(['test', '123'], 'test "123"')
@ -133,9 +138,12 @@ class TestTokenizer(unittest.TestCase):
r'test "foo\"bar" baz 123')
def test_unbalanced_quotes(self):
ex = exceptions.MpdArgError
msg = 'Invalid unquoted character'
self.assertTokenizeRaisesError('test "foo bar" baz"', msg)
self.assertTokenizeRaises(ex, msg, 'test "foo bar" baz"')
def test_missing_closing_quote(self):
self.assertTokenizeRaisesError('test "foo', 'Missing closing \'"\'')
self.assertTokenizeRaisesError('test "foo a ', 'Missing closing \'"\'')
ex = exceptions.MpdArgError
msg = 'Missing closing \'"\''
self.assertTokenizeRaises(ex, msg, 'test "foo')
self.assertTokenizeRaises(ex, msg, 'test "foo a ')