]> git.llucax.com Git - software/pymin.git/blobdiff - dispatcher.py
Update TODO (add logging).
[software/pymin.git] / dispatcher.py
index 2f545cd6e91fb7351c65b223092b253863b5a0a6..b78db93a3e0f042c273821dda82c44450aec8403 100644 (file)
@@ -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