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).
"""
def __init__(self, command):
self.command = command
def __str__(self):
- return repr(self.command)
+ return ' '.join(self.command)
class CommandNotFoundError(Error):
r"""
"""
pass
+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
"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)
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()
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
import cPickle as pickle
except ImportError:
import pickle
+try:
+ from dispatcher import handler
+except ImportError:
+ def handler(f): return f # NOP for testing
__ALL__ = ('DhcpHandler',)
r"Initialize HostHandler object, see class documentation for details."
self.hosts = hosts
+ @handler
def add(self, name, ip, mac):
r"add(name, ip, mac) -> None :: Add a host to the hosts list."
# XXX deberia indexar por hostname o por ip? o por mac? :)
# nombres? Una MAC con muchas IP? una MAC con muchos nombre? Etc...
self.hosts[name] = Host(name, ip, mac)
+ @handler
def update(self, name, ip=None, mac=None):
r"update(name[, ip[, mac]]) -> None :: Update a host of the hosts list."
if not name in self.hosts:
if mac is not None:
self.hosts[name].mac = mac
+ @handler
def delete(self, name):
r"delete(name) -> None :: Delete a host of the hosts list."
if not name in self.hosts:
raise KeyError('Host not found')
del self.hosts[name]
+ @handler
def list(self):
r"""list() -> CSV string :: List all the hostnames.
"""
return ','.join(self.hosts)
+ @handler
def show(self):
r"""show() -> CSV string :: List all the complete hosts information.
self._write_config()
self.host = HostHandler(self.hosts)
+ @handler
def set(self, param, value):
r"set(param, value) -> None :: Set a DHCP parameter."
if not param in self.vars:
raise KeyError('Parameter ' + param + ' not found')
self.vars[param] = value
+ @handler
def list(self):
r"""list() -> CSV string :: List all the parameter names.
"""
return ','.join(self.vars)
+ @handler
def show(self):
r"""show() -> CSV string :: List all the parameters (with their values).
"""
return '\n'.join(('%s,%s' % (k, v) for (k, v) in self.vars.items()))
+ @handler
def start(self):
r"start() -> None :: Start the DHCP service."
#esto seria para poner en una interfaz
#y seria el hook para arrancar el servicio
pass
+ @handler
def stop(self):
r"stop() -> None :: Stop the DHCP service."
#esto seria para poner en una interfaz
#y seria el hook para arrancar el servicio
pass
+ @handler
def restart(self):
r"restart() -> None :: Restart the DHCP service."
#esto seria para poner en una interfaz
#y seria el hook para arrancar el servicio
pass
+ @handler
def reload(self):
r"reload() -> None :: Reload the configuration of the DHCP service."
#esto seria para poner en una interfaz
#y seria el hook para arrancar el servicio
pass
+ @handler
def commit(self):
r"commit() -> None :: Commit the changes and reload the DHCP service."
#esto seria para poner en una interfaz
self._write_config()
self.reload()
+ @handler
def rollback(self):
r"rollback() -> None :: Discard the changes not yet commited."
self._load()