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).
"""
+ pass
- def __init__(self, command):
- r"""Initialize the Error object.
+class HandlerError(Error):
+ r"""
+ HandlerError(command) -> HandlerError instance :: Base handlers exception.
- See Error class documentation for more info.
- """
- self.command = command
+ All exceptions raised by the handlers should inherit from this one, so
+ dispatching errors could be separated from real programming errors (bugs).
+ """
+ pass
- def __str__(self):
- return repr(self.command)
class CommandNotFoundError(Error):
r"""
This exception is raised when the command received can't be dispatched
because there is no handlers to process it.
"""
- pass
+
+ def __init__(self, command):
+ r"""Initialize the Error object.
+
+ See Error class documentation for more info.
+ """
+ self.command = command
+
+ def __str__(self):
+ return 'Command not found: "%s"' % ' '.join(self.command)
+
+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