All exceptions raised by the Dispatcher inherits from this one, so you can
easily catch any dispatching exception.
- command - is the command that raised the exception.
+ command - is the command that raised the exception, expressed as a list of
+ paths (or subcommands).
"""
def __init__(self, command):
self.command = command
def __str__(self):
- return repr(self.command)
+ return 'Command not found: "%s"' % ' '.join(self.command)
class CommandNotFoundError(Error):
r"""
"""
pass
+def handler(f):
+ f._dispatcher_handler = True
+ return f
+
+def is_handler(handler):
+ return callable(handler) and hasattr(handler, '_dispatcher_handler') \
+ and handler._dispatcher_handler
+
class Dispatcher:
r"""Dispatcher([routes]) -> Dispatcher instance :: Command dispatcher
"tree" and call it, or raises a CommandNotFoundError if the command
can't be dispatched.
"""
+ command = list()
route = route.split() # TODO support "" and keyword arguments
if not route:
- raise CommandNotFoundError('') # TODO better error reporting
+ raise CommandNotFoundError(command)
+ command.append(route[0])
handler = self.routes.get(route[0], None)
+ if handler is None:
+ raise CommandNotFoundError(command)
route = route[1:]
- while not callable(handler):
- if not route:
- raise CommandNotFoundError('XXX') # TODO better error reporting
+ while not is_handler(handler):
+ if len(route) is 0:
+ raise CommandNotFoundError(command)
+ command.append(route[0])
if not hasattr(handler, route[0]):
- raise CommandNotFoundError(route[0]) # TODO better error rep.
+ raise CommandNotFoundError(command)
handler = getattr(handler, route[0])
route = route[1:]
- handler(*route)
+ return handler(*route)
if __name__ == '__main__':
+ @handler
def test_func(*args):
print 'func:', args
class TestClassSubHandler:
+ @handler
def subcmd(self, *args):
print 'class.subclass.subcmd:', args
class TestClass:
+ @handler
def cmd1(self, *args):
print 'class.cmd1:', args
+ @handler
def cmd2(self, *args):
print 'class.cmd2:', args
subclass = TestClassSubHandler()
except CommandNotFoundError, e:
print 'Not found:', e
try:
- d.dispatch('sucutrule')
+ d.dispatch('sucutrule piquete culete')
except CommandNotFoundError, e:
print 'Not found:', e
try:
- d.dispatch('inst cmd3')
+ d.dispatch('inst cmd3 arg1 arg2 arg3')
except CommandNotFoundError, e:
print 'Not found:', e