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.
# 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 \
-(
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')
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
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.
"""
def dispatch(self, route):
r"""dispatch(route) -> None :: Dispatch a command string.
def dispatch(self, route):
r"""dispatch(route) -> None :: Dispatch a command string.
(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:]
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)
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'))
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
# Parser tests
p = parse_command('hello world')
# Parser tests
p = parse_command('hello world')
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.
# 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 ..."
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()
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()