]> 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.
 
     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"""
 
 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.
     """
     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
 
 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.
         """
         "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:
         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)
         handler = self.routes.get(route[0], None)
+        if handler is None:
+            raise CommandNotFoundError(command)
         route = route[1:]
         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]):
             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 = getattr(handler, route[0])
             route = route[1:]
-        handler(*route)
+        return handler(*route)
 
 
 if __name__ == '__main__':
 
 
 
 if __name__ == '__main__':
 
+    @handler
     def test_func(*args):
           print 'func:', args
 
     class TestClassSubHandler:
     def test_func(*args):
           print 'func:', args
 
     class TestClassSubHandler:
+        @handler
         def subcmd(self, *args):
             print 'class.subclass.subcmd:', args
 
     class TestClass:
         def subcmd(self, *args):
             print 'class.subclass.subcmd:', args
 
     class TestClass:
+        @handler
         def cmd1(self, *args):
             print 'class.cmd1:', args
         def cmd1(self, *args):
             print 'class.cmd1:', args
+        @handler
         def cmd2(self, *args):
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
         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:
     except CommandNotFoundError, e:
         print 'Not found:', e
     try:
-        d.dispatch('sucutrule')
+        d.dispatch('sucutrule piquete culete')
     except CommandNotFoundError, e:
         print 'Not found:', e
     try:
     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
 
     except CommandNotFoundError, e:
         print 'Not found:', e