X-Git-Url: https://git.llucax.com/software/pymin.git/blobdiff_plain/026f5f3a6274709b7863c619c979dd32f0ee686f..28063e4b7779eff7ac0fa5c9939545d2091ef24c:/dispatcher.py diff --git a/dispatcher.py b/dispatcher.py index 2f545cd..b78db93 100644 --- a/dispatcher.py +++ b/dispatcher.py @@ -15,18 +15,20 @@ class Error(RuntimeError): 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""" @@ -35,7 +37,24 @@ class CommandNotFoundError(Error): 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 @@ -82,33 +101,42 @@ class 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() @@ -126,11 +154,11 @@ if __name__ == '__main__': 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