]> git.llucax.com Git - software/pymin.git/commitdiff
Use a handler object as the root dispatcher handler instead of a dict.
authorLeandro Lucarella <llucarella@integratech.com.ar>
Fri, 5 Oct 2007 16:01:53 +0000 (13:01 -0300)
committerLeandro Lucarella <llucarella@integratech.com.ar>
Fri, 5 Oct 2007 16:27:03 +0000 (13:27 -0300)
Now the dispatcher use a handler object as the root handler. This way you
can inherit your root handler from Handler and get the useful 'help' and
'coommands' commands for free.

config.py
pymin/dispatcher.py
pymin/pymindaemon.py
pymind

index 059faaeea54762900ef6162904c8888a767a0b30..5ae043d9ac0f3aa10f308c04590d3aed6a8b8f0e 100644 (file)
--- a/config.py
+++ b/config.py
@@ -1,36 +1,24 @@
 # vim: set et sts=4 sw=4 encoding=utf-8 :
 
 from pymin.services import *
 # vim: set et sts=4 sw=4 encoding=utf-8 :
 
 from pymin.services import *
-from pymin.dispatcher import handler
+from pymin.dispatcher import Handler
 
 
-# XXX for testing only
-@handler
-def test_func(*args):
-    print 'func:', args
-
-routes = dict \
-(
+class Root(Handler):
     dhcp = DhcpHandler(
         pickle_dir = 'var/lib/pymin/pickle/dhcp',
     dhcp = DhcpHandler(
         pickle_dir = 'var/lib/pymin/pickle/dhcp',
-        config_dir = 'var/lib/pymin/config/dhcp',
-    ),
+        config_dir = 'var/lib/pymin/config/dhcp')
     dns = DnsHandler(
         pickle_dir = 'var/lib/pymin/pickle/dns',
     dns = DnsHandler(
         pickle_dir = 'var/lib/pymin/pickle/dns',
-        config_dir = 'var/lib/pymin/config/dns',
-    ),
+        config_dir = 'var/lib/pymin/config/dns')
     firewall = FirewallHandler(
         pickle_dir = 'var/lib/pymin/pickle/firewall',
     firewall = FirewallHandler(
         pickle_dir = 'var/lib/pymin/pickle/firewall',
-        config_dir = 'var/lib/pymin/config/firewall',
-    ),
+        config_dir = 'var/lib/pymin/config/firewall')
     ip = IpHandler(
         pickle_dir = 'var/lib/pymin/pickle/ip',
     ip = IpHandler(
         pickle_dir = 'var/lib/pymin/pickle/ip',
-        config_dir = 'var/lib/pymin/config/ip',
-    ),
+        config_dir = 'var/lib/pymin/config/ip')
     proxy = ProxyHandler(
         pickle_dir = 'var/lib/pymin/pickle/proxy',
     proxy = ProxyHandler(
         pickle_dir = 'var/lib/pymin/pickle/proxy',
-        config_dir = 'var/lib/pymin/config/proxy',
-    ),
-)
+        config_dir = 'var/lib/pymin/config/proxy')
 
 bind_addr = \
 (
 
 bind_addr = \
 (
index c7d260bda6f1910d27b610a3f79f4b579613256e..7e9ef6079d9a9d66d3a681db0591b1ff0e85682c 100644 (file)
@@ -294,15 +294,13 @@ def parse_command(command):
     return (seq, dic)
 
 class Dispatcher:
     return (seq, dic)
 
 class Dispatcher:
-    r"""Dispatcher([routes]) -> Dispatcher instance :: Command dispatcher
+    r"""Dispatcher([root]) -> Dispatcher instance :: Command dispatcher.
 
     This class provides a modular and extensible dispatching mechanism. You
 
     This class provides a modular and extensible dispatching mechanism. You
-    can specify root 'routes' (as a dict where the key is the string of the
-    root command and the value is a callable object to handle that command,
-    or a subcommand if the callable is an instance and the command can be
-    sub-routed).
+    specify a root handler (probably as a pymin.dispatcher.Handler subclass),
 
 
-    The command can have arguments, separated by (any number of) spaces.
+    The command can have arguments, separated by (any number of) spaces and
+    keyword arguments (see parse_command for more details).
 
     The dispatcher tries to route the command as deeply as it can, passing
     the other "path" components as arguments to the callable. To route the
 
     The dispatcher tries to route the command as deeply as it can, passing
     the other "path" components as arguments to the callable. To route the
@@ -311,25 +309,26 @@ class Dispatcher:
 
     Example:
     >>> d = Dispatcher(dict(handler=some_handler))
 
     Example:
     >>> d = Dispatcher(dict(handler=some_handler))
-    >>> d.dispatch('handler attribute method arg1 arg2 "third argument"')
+    >>> d.dispatch('handler attribute method arg1 "arg 2" arg=3')
 
     If 'some_handler' is an object with an 'attribute' that is another
     object which has a method named 'method', then
 
     If 'some_handler' is an object with an 'attribute' that is another
     object which has a method named 'method', then
-    some_handler.attribute.method('arg1', 'arg2') will be called. If
-    some_handler is a function, then some_handler('attribute', 'method',
-    'arg1', 'arg2') will be called. The handler "tree" can be as complex
-    and deep as you want.
-
-    If some command can't be dispatched (because there is no root handler or
-    there is no matching callable attribute), a CommandNotFoundError is raised.
+    some_handler.attribute.method('arg1', 'arg 2', arg=3) will be called.
+    If some_handler is a function, then some_handler('attribute', 'method',
+    'arg1', 'arg 2', arg=3) will be called. The handler "tree" can be as
+    complex and deep as you want.
+
+    If some command can't be dispatched (because there is no root handler
+    or there is no matching callable attribute), a CommandNotFoundError
+    is raised.
     """
 
     """
 
-    def __init__(self, routes=dict()):
+    def __init__(self, root):
         r"""Initialize the Dispatcher object.
 
         See Dispatcher class documentation for more info.
         """
         r"""Initialize the Dispatcher object.
 
         See Dispatcher class documentation for more info.
         """
-        self.routes = routes
+        self.root = root
 
     def dispatch(self, route):
         r"""dispatch(route) -> None :: Dispatch a command string.
 
     def dispatch(self, route):
         r"""dispatch(route) -> None :: Dispatch a command string.
@@ -342,11 +341,7 @@ class Dispatcher:
         (route, kwargs) = parse_command(route)
         if not route:
             raise CommandNotFoundError(command)
         (route, kwargs) = parse_command(route)
         if not route:
             raise CommandNotFoundError(command)
-        command.append(route[0])
-        handler = self.routes.get(route[0], None)
-        if handler is None:
-            raise CommandNotFoundError(command)
-        route = route[1:]
+        handler = self.root
         while not is_handler(handler):
             if len(route) is 0:
                 raise CommandNotFoundError(command)
         while not is_handler(handler):
             if len(route) is 0:
                 raise CommandNotFoundError(command)
@@ -378,12 +373,11 @@ if __name__ == '__main__':
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
 
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
 
-    test_class = TestClass()
+    class RootHandler(Handler):
+        func = staticmethod(test_func)
+        inst = TestClass()
 
 
-    d = Dispatcher(dict(
-            func=test_func,
-            inst=test_class,
-    ))
+    d = Dispatcher(RootHandler())
 
     d.dispatch(r'''func arg1 arg2 arg3 "fourth 'argument' with \", a\ttab and\n\\n"''')
     print 'inst commands:', tuple(d.dispatch('inst commands'))
 
     d.dispatch(r'''func arg1 arg2 arg3 "fourth 'argument' with \", a\ttab and\n\\n"''')
     print 'inst commands:', tuple(d.dispatch('inst commands'))
@@ -404,6 +398,8 @@ if __name__ == '__main__':
         d.dispatch('inst cmd3 arg1 arg2 arg3')
     except CommandNotFoundError, e:
         print 'Not found:', e
         d.dispatch('inst cmd3 arg1 arg2 arg3')
     except CommandNotFoundError, e:
         print 'Not found:', e
+    print
+    print
 
     # Parser tests
     p = parse_command('hello world')
 
     # Parser tests
     p = parse_command('hello world')
index be2c9750d29339d7b79d696bdf6218898ed267c8..ee5f80544837d41a85b657ed252a4e4438f49656 100644 (file)
@@ -11,28 +11,33 @@ command-line.
 import signal
 import socket
 
 import signal
 import socket
 
+from pymin.dispatcher import handler
+from pymin import dispatcher
 from pymin import eventloop
 from pymin import serializer
 
 class PyminDaemon(eventloop.EventLoop):
 from pymin import eventloop
 from pymin import serializer
 
 class PyminDaemon(eventloop.EventLoop):
-    r"""PyminDaemon(bind_addr, routes) -> PyminDaemon instance
+    r"""PyminDaemon(root, bind_addr) -> PyminDaemon instance
 
     This class is well suited to run as a single process. It handles
     signals for controlled termination (SIGINT and SIGTERM), as well as
     a user signal to reload the configuration files (SIGUSR1).
 
 
     This class is well suited to run as a single process. It handles
     signals for controlled termination (SIGINT and SIGTERM), as well as
     a user signal to reload the configuration files (SIGUSR1).
 
-    bind_addr - is a tuple of (ip, port) where to bind the UDP socket to.
+    root - the root handler. This is passed directly to the Dispatcher.
 
 
-    routes - is a dictionary where the key is a command string and the value
-             is the command handler. This is passed directly to the Dispatcher.
+    bind_addr - is a tuple of (ip, port) where to bind the UDP socket to.
 
     Here is a simple usage example:
 
 
     Here is a simple usage example:
 
-    >>> def test_handler(*args): print 'test:', args
-    >>> PyminDaemon(('', 9999), dict(test=test_handler)).run()
+    >>> from pymin import dispatcher
+    >>> class Root(dispatcher.Handler):
+            @handler('Test command.')
+            def test(self, *args):
+                print 'test:', args
+    >>> PyminDaemon(Root(), ('', 9999)).run()
     """
 
     """
 
-    def __init__(self, routes=dict(), bind_addr=('', 9999)):
+    def __init__(self, root, bind_addr=('', 9999)):
         r"""Initialize the PyminDaemon object.
 
         See PyminDaemon class documentation for more info.
         r"""Initialize the PyminDaemon object.
 
         See PyminDaemon class documentation for more info.
@@ -44,7 +49,7 @@ class PyminDaemon(eventloop.EventLoop):
         # Create EventLoop
         eventloop.EventLoop.__init__(self, sock)
         # Create Dispatcher
         # Create EventLoop
         eventloop.EventLoop.__init__(self, sock)
         # Create Dispatcher
-        self.dispatcher = Dispatcher(routes)
+        self.dispatcher = dispatcher.Dispatcher(root)
         # Signal handling
         def quit(signum, frame):
             print "Shuting down ..."
         # Signal handling
         def quit(signum, frame):
             print "Shuting down ..."
@@ -87,14 +92,14 @@ class PyminDaemon(eventloop.EventLoop):
 
 if __name__ == '__main__':
 
 
 if __name__ == '__main__':
 
-    @handler(u"Print all the arguments, return nothing.")
-    def test_handler(*args):
-        print 'test:', args
-
-    @handler(u"Echo the message passed as argument.")
-    def echo_handler(message):
-        print 'echo:', message
-        return message
+    class Root(dispatcher.Handler):
+        @handler(u"Print all the arguments, return nothing.")
+        def test(self, *args):
+            print 'test:', args
+        @handler(u"Echo the message passed as argument.")
+        def echo(self, message):
+            print 'echo:', message
+            return message
 
 
-    PyminDaemon(dict(test=test_handler, echo=echo_handler)).run()
+    PyminDaemon(Root()).run()
 
 
diff --git a/pymind b/pymind
index 27a972269c7597f73a4fe40926cc592a90bf0e9b..a04307d1920909bbd3a25cce42c0c9d8fbb5dbcf 100755 (executable)
--- a/pymind
+++ b/pymind
@@ -4,5 +4,5 @@
 from pymin.pymindaemon import PyminDaemon
 import config
 
 from pymin.pymindaemon import PyminDaemon
 import config
 
-PyminDaemon(config.routes, config.bind_addr).run()
+PyminDaemon(config.Root(), config.bind_addr).run()