diff --git a/mopidy/mpd/protocol/__init__.py b/mopidy/mpd/protocol/__init__.py index c86a39e6..1be42dcc 100644 --- a/mopidy/mpd/protocol/__init__.py +++ b/mopidy/mpd/protocol/__init__.py @@ -14,6 +14,8 @@ from __future__ import unicode_literals import inspect +from mopidy.mpd import exceptions + #: The MPD protocol uses UTF-8 for encoding all data. ENCODING = 'UTF-8' @@ -79,7 +81,7 @@ class Commands(object): def add(self, name, auth_required=True, list_command=True, **validators): def wrapper(func): if name in self.handlers: - raise Exception('%s already registered' % name) + raise ValueError('%s already registered' % name) args, varargs, keywords, defaults = inspect.getargspec(func) defaults = dict(zip(args[-len(defaults or []):], defaults or [])) @@ -104,7 +106,10 @@ class Commands(object): for key, value in callargs.items(): default = defaults.get(key, object()) if key in validators and value != default: - callargs[key] = validators[key](value) + try: + callargs[key] = validators[key](value) + except ValueError: + raise exceptions.MpdArgError('incorrect arguments') return func(**callargs) validate.auth_required = auth_required @@ -114,11 +119,10 @@ class Commands(object): return wrapper def call(self, args, context=None): - # TODO: raise mopidy.mpd.exceptions if not args: - raise TypeError('No args provided') + raise exceptions.MpdNoCommand() if args[0] not in self.handlers: - raise LookupError('Unknown command') + raise exceptions.MpdUnknownCommand(command=args[0]) return self.handlers[args[0]](context, *args[1:]) diff --git a/tests/mpd/test_commands.py b/tests/mpd/test_commands.py index 845796af..91a9125a 100644 --- a/tests/mpd/test_commands.py +++ b/tests/mpd/test_commands.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import unittest -from mopidy.mpd import protocol +from mopidy.mpd import exceptions, protocol class TestConverts(unittest.TestCase): @@ -134,7 +134,7 @@ class TestCommands(unittest.TestCase): self.assertEqual(sentinel3, self.commands.call(['baz'])) def test_call_with_nonexistent_handler(self): - with self.assertRaises(LookupError): + with self.assertRaises(exceptions.MpdUnknownCommand): self.commands.call(['bar']) def test_call_passes_context(self): @@ -144,7 +144,7 @@ class TestCommands(unittest.TestCase): sentinel, self.commands.call(['foo'], context=sentinel)) def test_call_without_args_fails(self): - with self.assertRaises(TypeError): + with self.assertRaises(exceptions.MpdNoCommand): self.commands.call([]) def test_call_passes_required_argument(self): @@ -212,6 +212,16 @@ class TestCommands(unittest.TestCase): func = lambda context: True self.commands.add('bar', context=lambda v: v)(func) + def test_validator_value_error_is_converted(self): + def validdate(value): + raise ValueError + + func = lambda context, arg: True + self.commands.add('bar', arg=validdate)(func) + + with self.assertRaises(exceptions.MpdArgError): + self.commands.call(['bar', 'test']) + def test_auth_required_gets_stored(self): func1 = lambda context: context func2 = lambda context: context