]> git.llucax.com Git - software/pymin.git/commitdiff
Improve a lot error reporting and unicode/utf-8 compatibility.
authorLeandro Lucarella <llucax@gmail.com>
Sat, 6 Oct 2007 04:02:35 +0000 (01:02 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Sat, 6 Oct 2007 04:02:35 +0000 (01:02 -0300)
Conversion between unicode and utf-8 is now done when sending/receiving
over the network by the PyminDaemon.

All errors provides now a conversion to unicode.

Dispatcher CommandNotFoundError was refactored to multiple classes with
specific and more descriptive error messages.

Handlers now can have a little help string (handler_help).

Handler's help command now list subhandlers (using handler_help).

A new error was added for help command (HelpNotFoundError).

All service handlers were updated.

TODO
pymin/dispatcher.py
pymin/pymindaemon.py
pymin/services/dhcp/__init__.py
pymin/services/dns/__init__.py
pymin/services/firewall/__init__.py
pymin/services/ip/__init__.py
pymin/services/proxy/__init__.py

diff --git a/TODO b/TODO
index 362b434a91b895c8e25d83965ca2bf00dc3d831c..b8d9c03853380c9db7272a5ad4f9ff6513a309fd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,19 +1,6 @@
 
 Ideas / TODO:
 
 
 Ideas / TODO:
 
-* Hacer el protocolo completamente introspectivo, de manera que el cliente pueda
-  ser muy simple y genérico y en caso de agregar funcionalidad no sea necesario
-  modificarlo.
-
-* Evaluar hacer un RootHandler en vez de un diccionario con los handlers de la
-  raiz para simplificar la introspección y tener un help/commands global.
-
-* Evaluar que el dispatcher vea si se llama a un HandlerContainer y de ser así
-  que tire una ayuda en vez de un CommandNotFound (por ejemplo si se pone:
-  "dhcp" solo que tire una ayuda). Y si hay un subcomando no encontrado, que
-  tire un Command Not Found in handler (por ej "dhcp lala" -> Command "lala" not
-  found in "dhcp").
-
 * Agregar logging.
 
 * Agregar validación con formencode.
 * Agregar logging.
 
 * Agregar validación con formencode.
index 7e9ef6079d9a9d66d3a681db0591b1ff0e85682c..39b4b75cf6522f64e78b2d097422a2bfc69285e1 100644 (file)
@@ -19,7 +19,16 @@ class Error(RuntimeError):
     command - is the command that raised the exception, expressed as a list of
               paths (or subcommands).
     """
     command - is the command that raised the exception, expressed as a list of
               paths (or subcommands).
     """
-    pass
+
+    def __init__(self, message):
+        r"Initialize the Error object. See class documentation for more info."
+        self.message = message
+
+    def __unicode__(self):
+        return self.message
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
 
 class HandlerError(Error):
     r"""HandlerError(command) -> HandlerError instance :: Base handlers error.
 
 class HandlerError(Error):
     r"""HandlerError(command) -> HandlerError instance :: Base handlers error.
@@ -37,25 +46,59 @@ class CommandError(Error):
     """
 
     def __init__(self, command):
     """
 
     def __init__(self, command):
-        r"""Initialize the object.
-
-        See class documentation for more info.
-        """
+        r"Initialize the object, see class documentation for more info."
         self.command = command
 
         self.command = command
 
-    def __str__(self):
-        return 'Command error: "%s"' % self.command
+    def __unicode__(self):
+        return u'Error in command "%s".' % u' '.join(self.command)
+
+class CommandNotSpecifiedError(CommandError):
+    r"""CommandNotSpecifiedError() -> CommandNotSpecifiedError instance.
+
+    This exception is raised when an empty command string is received.
+    """
+
+    def __init__(self):
+        r"Initialize the object, see class documentation for more info."
+        pass
+
+    def __unicode__(self):
+        return u'Command not specified.'
+
+class CommandIsAHandlerError(CommandError):
+    r"""CommandIsAHandlerError() -> CommandIsAHandlerError instance.
+
+    This exception is raised when a command is a handler containing commands
+    instead of a command itself.
+    """
+
+    def __unicode__(self):
+        command = ' '.join(self.command)
+        return u'"%s" is a handler, not a command (type "%s help" for help).' \
+                    % (command, command)
+
+class CommandNotInHandlerError(CommandError):
+    r"""CommandNotInHandlerError() -> CommandNotInHandlerError instance.
+
+    This exception is raised when a command parent is a hanlder containing
+    commands, but the command itself is not found.
+    """
+
+    def __unicode__(self):
+        return u'Command "%(c)s" not found in handler "%(h)s" ' \
+                u'(type "%(h)s help" for help).' \
+                        % dict(c=u' '.join(self.command[-1:]),
+                                h=u' '.join(self.command[0:-1]))
 
 class CommandNotFoundError(CommandError):
 
 class CommandNotFoundError(CommandError):
-    r"""CommandNotFoundError(command) -> CommandNotFoundError instance.
+    r"""CommandNotFoundError(command[, handler]) -> CommandNotFoundError object.
 
     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.
     """
 
-    def __str__(self):
-        return 'Command not found: "%s"' % ' '.join(
-                                                repr(c) for c in self.command)
+    def __unicode__(self):
+        return u'Command "%s" not found.' % u' '.join(self.command)
 
 class ParseError(CommandError):
     r"""ParseError(command[, desc]) -> ParseError instance
 
 class ParseError(CommandError):
     r"""ParseError(command[, desc]) -> ParseError instance
@@ -75,8 +118,26 @@ class ParseError(CommandError):
         self.command = command
         self.desc = desc
 
         self.command = command
         self.desc = desc
 
-    def __str__(self):
-        return 'Syntax error, %s: %s' % (self.desc, self.command)
+    def __unicode__(self):
+        return u'Syntax error, %s: %s' % (self.desc, self.command)
+
+class HelpNotFoundError(Error):
+    r"""HelpNotFoundError(command) -> HelpNotFoundError instance.
+
+    This exception is raised when a help command can't find the command
+    asked for help.
+    """
+
+    def __init__(self, command):
+        r"""Initialize the object.
+
+        See class documentation for more info.
+        """
+        self.command = command
+
+    def __unicode__(self):
+        return u"Can't get help for '%s', command not found." % self.command
+
 
 def handler(help):
     r"""handler(help) -> function wrapper :: Mark a callable as a handler.
 
 def handler(help):
     r"""handler(help) -> function wrapper :: Mark a callable as a handler.
@@ -88,33 +149,32 @@ def handler(help):
     def wrapper(f):
         if not help:
             raise TypeError("'help' should not be empty")
     def wrapper(f):
         if not help:
             raise TypeError("'help' should not be empty")
-        f._dispatcher_help = help
+        f._dispatcher_handler = True
+        f.handler_help = help
         return f
     return wrapper
 
 def is_handler(handler):
     r"is_handler(handler) -> bool :: Tell if a object is a handler."
         return f
     return wrapper
 
 def is_handler(handler):
     r"is_handler(handler) -> bool :: Tell if a object is a handler."
-    return callable(handler) and hasattr(handler, '_dispatcher_help')
-
-def get_help(handler):
-    r"get_help(handler) -> unicode :: Get a handler's help string."
-    if not is_handler(handler):
-        raise TypeError("'%s' should be a handler" % handler.__name__)
-    return handler._dispatcher_help
+    return callable(handler) and hasattr(handler, '_dispatcher_handler') \
+                and handler._dispatcher_handler
 
 class Handler:
     r"""Handler() -> Handler instance :: Base class for all dispatcher handlers.
 
     All dispatcher handlers should inherit from this class to have some extra
 
 class Handler:
     r"""Handler() -> Handler instance :: Base class for all dispatcher handlers.
 
     All dispatcher handlers should inherit from this class to have some extra
-    commands, like help.
+    commands, like help. You should override the 'handler_help' attribute to a
+    nice help message describing the handler.
     """
 
     """
 
-    @handler(u'List available commands.')
+    handler_help = u'Undocumented handler'
+
+    @handler(u'List available commands')
     def commands(self):
         r"""commands() -> generator :: List the available commands."""
         return (a for a in dir(self) if is_handler(getattr(self, a)))
 
     def commands(self):
         r"""commands() -> generator :: List the available commands."""
         return (a for a in dir(self) if is_handler(getattr(self, a)))
 
-    @handler(u'Show available commands with their help.')
+    @handler(u'Show available commands with their help')
     def help(self, command=None):
         r"""help([command]) -> unicode/dict :: Show help on available commands.
 
     def help(self, command=None):
         r"""help([command]) -> unicode/dict :: Show help on available commands.
 
@@ -123,14 +183,19 @@ class Handler:
         and values are the help strings.
         """
         if command is None:
         and values are the help strings.
         """
         if command is None:
-            return dict((a, get_help(getattr(self, a)))
-                        for a in dir(self) if is_handler(getattr(self, a)))
-        if not hasattr(self, command):
-            raise CommandNotFoundError(command)
-        handler = getattr(self, command)
-        if not is_handler(handler):
-            raise CommandNotFoundError(command)
-        return get_help(handler)
+            d = dict()
+            for a in dir(self):
+                h = getattr(self, a)
+                if is_handler(h) or isinstance(h, Handler):
+                    d[a] = h.handler_help
+            return d
+        # A command was specified
+        if not hasattr(self, command.encode('utf-8')):
+            raise HelpNotFoundError(command)
+        handler = getattr(self, command.encode('utf-8'))
+        if not is_handler(handler) and not hasattr(handler):
+            raise HelpNotFoundError(command)
+        return handler.handler_help
 
 def parse_command(command):
     r"""parse_command(command) -> (args, kwargs) :: Parse a command.
 
 def parse_command(command):
     r"""parse_command(command) -> (args, kwargs) :: Parse a command.
@@ -318,9 +383,7 @@ class Dispatcher:
     'arg1', 'arg 2', arg=3) will be called. The handler "tree" can be as
     complex and deep as you want.
 
     '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.
+    If some command can't be dispatched, a CommandError subclass is raised.
     """
 
     def __init__(self, root):
     """
 
     def __init__(self, root):
@@ -334,41 +397,47 @@ class Dispatcher:
         r"""dispatch(route) -> None :: Dispatch a command string.
 
         This method searches for a suitable callable object in the routes
         r"""dispatch(route) -> None :: Dispatch a command string.
 
         This method searches for a suitable callable object in the routes
-        "tree" and call it, or raises a CommandNotFoundError if the command
+        "tree" and call it, or raises a CommandError subclass if the command
         can't be dispatched.
         can't be dispatched.
+
+        route - *unicode* string with the command route.
         """
         command = list()
         (route, kwargs) = parse_command(route)
         if not route:
         """
         command = list()
         (route, kwargs) = parse_command(route)
         if not route:
-            raise CommandNotFoundError(command)
+            raise CommandNotSpecifiedError()
         handler = self.root
         while not is_handler(handler):
             if len(route) is 0:
         handler = self.root
         while not is_handler(handler):
             if len(route) is 0:
+                if isinstance(handler, Handler):
+                    raise CommandIsAHandlerError(command)
                 raise CommandNotFoundError(command)
             command.append(route[0])
                 raise CommandNotFoundError(command)
             command.append(route[0])
-            if not hasattr(handler, route[0]):
+            if not hasattr(handler, route[0].encode('utf-8')):
+                if isinstance(handler, Handler) and len(command) > 1:
+                    raise CommandNotInHandlerError(command)
                 raise CommandNotFoundError(command)
                 raise CommandNotFoundError(command)
-            handler = getattr(handler, route[0])
+            handler = getattr(handler, route[0].encode('utf-8'))
             route = route[1:]
         return handler(*route, **kwargs)
 
 
 if __name__ == '__main__':
 
             route = route[1:]
         return handler(*route, **kwargs)
 
 
 if __name__ == '__main__':
 
-    @handler(u"test: Print all the arguments, return nothing.")
+    @handler(u"test: Print all the arguments, return nothing")
     def test_func(*args):
         print 'func:', args
 
     class TestClassSubHandler(Handler):
     def test_func(*args):
         print 'func:', args
 
     class TestClassSubHandler(Handler):
-        @handler(u"subcmd: Print all the arguments, return nothing.")
+        @handler(u"subcmd: Print all the arguments, return nothing")
         def subcmd(self, *args):
             print 'class.subclass.subcmd:', args
 
     class TestClass(Handler):
         def subcmd(self, *args):
             print 'class.subclass.subcmd:', args
 
     class TestClass(Handler):
-        @handler(u"cmd1: Print all the arguments, return nothing.")
+        @handler(u"cmd1: Print all the arguments, return nothing")
         def cmd1(self, *args):
             print 'class.cmd1:', args
         def cmd1(self, *args):
             print 'class.cmd1:', args
-        @handler(u"cmd2: Print all the arguments, return nothing.")
+        @handler(u"cmd2: Print all the arguments, return nothing")
         def cmd2(self, *args):
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
         def cmd2(self, *args):
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
@@ -388,7 +457,7 @@ if __name__ == '__main__':
     d.dispatch('inst subclass subcmd arg1 arg2 arg3 arg4 arg5')
     try:
         d.dispatch('')
     d.dispatch('inst subclass subcmd arg1 arg2 arg3 arg4 arg5')
     try:
         d.dispatch('')
-    except CommandNotFoundError, e:
+    except CommandNotSpecifiedError, e:
         print 'Not found:', e
     try:
         d.dispatch('sucutrule piquete culete')
         print 'Not found:', e
     try:
         d.dispatch('sucutrule piquete culete')
@@ -396,7 +465,11 @@ if __name__ == '__main__':
         print 'Not found:', e
     try:
         d.dispatch('inst cmd3 arg1 arg2 arg3')
         print 'Not found:', e
     try:
         d.dispatch('inst cmd3 arg1 arg2 arg3')
-    except CommandNotFoundError, e:
+    except CommandNotInHandlerError, e:
+        print 'Not found:', e
+    try:
+        d.dispatch('inst')
+    except CommandIsAHandlerError, e:
         print 'Not found:', e
     print
     print
         print 'Not found:', e
     print
     print
index ee5f80544837d41a85b657ed252a4e4438f49656..f7497536835ae72670cc2ca3acbcf55ba5d58ba3 100644 (file)
@@ -49,6 +49,7 @@ class PyminDaemon(eventloop.EventLoop):
         # Create EventLoop
         eventloop.EventLoop.__init__(self, sock)
         # Create Dispatcher
         # Create EventLoop
         eventloop.EventLoop.__init__(self, sock)
         # Create Dispatcher
+        #TODO root.pymin = PyminHandler()
         self.dispatcher = dispatcher.Dispatcher(root)
         # Signal handling
         def quit(signum, frame):
         self.dispatcher = dispatcher.Dispatcher(root)
         # Signal handling
         def quit(signum, frame):
@@ -65,7 +66,7 @@ class PyminDaemon(eventloop.EventLoop):
         r"handle() -> None :: Handle incoming events using the dispatcher."
         (msg, addr) = self.file.recvfrom(65535)
         try:
         r"handle() -> None :: Handle incoming events using the dispatcher."
         (msg, addr) = self.file.recvfrom(65535)
         try:
-            result = self.dispatcher.dispatch(msg)
+            result = self.dispatcher.dispatch(unicode(msg, 'utf-8'))
             if result is not None:
                 result = serializer.serialize(result)
             response = u'OK '
             if result is not None:
                 result = serializer.serialize(result)
             response = u'OK '
@@ -81,7 +82,7 @@ class PyminDaemon(eventloop.EventLoop):
             response += u'0\n'
         else:
             response += u'%d\n%s' % (len(result), result)
             response += u'0\n'
         else:
             response += u'%d\n%s' % (len(result), result)
-        self.file.sendto(response, addr)
+        self.file.sendto(response.encode('utf-8'), addr)
 
     def run(self):
         r"run() -> None :: Run the event loop (shortcut to loop())"
 
     def run(self):
         r"run() -> None :: Run the event loop (shortcut to loop())"
index 8f42e1ac013db09d6739720e8537285505b4023c..0dcb0d4abe3bb920ec93efb4eea00b67a41c91b5 100644 (file)
@@ -19,13 +19,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class HostError(Error, KeyError):
     r"""
 
 class HostError(Error, KeyError):
     r"""
@@ -36,7 +30,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -47,7 +41,7 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
 
 class HostNotFoundError(HostError):
     r"""
@@ -59,7 +53,7 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 
 class Host(Sequence):
 
 
 class Host(Sequence):
@@ -89,18 +83,20 @@ class HostHandler(Handler):
     hosts - A dictionary with string keys (hostnames) and Host instances values.
     """
 
     hosts - A dictionary with string keys (hostnames) and Host instances values.
     """
 
+    handler_help = u"Manage DHCP hosts"
+
     def __init__(self, hosts):
         r"Initialize HostHandler object, see class documentation for details."
         self.hosts = hosts
 
     def __init__(self, hosts):
         r"Initialize HostHandler object, see class documentation for details."
         self.hosts = hosts
 
-    @handler(u'Add a new host.')
+    @handler(u'Add a new host')
     def add(self, name, ip, mac):
         r"add(name, ip, mac) -> None :: Add a host to the hosts list."
         if name in self.hosts:
             raise HostAlreadyExistsError(name)
         self.hosts[name] = Host(name, ip, mac)
 
     def add(self, name, ip, mac):
         r"add(name, ip, mac) -> None :: Add a host to the hosts list."
         if name in self.hosts:
             raise HostAlreadyExistsError(name)
         self.hosts[name] = Host(name, ip, mac)
 
-    @handler(u'Update a host.')
+    @handler(u'Update a host')
     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:
     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:
@@ -110,26 +106,26 @@ class HostHandler(Handler):
         if mac is not None:
             self.hosts[name].mac = mac
 
         if mac is not None:
             self.hosts[name].mac = mac
 
-    @handler(u'Delete a host.')
+    @handler(u'Delete a host')
     def delete(self, name):
         r"delete(name) -> None :: Delete a host of the hosts list."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         del self.hosts[name]
 
     def delete(self, name):
         r"delete(name) -> None :: Delete a host of the hosts list."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         del self.hosts[name]
 
-    @handler(u'Get information about a host.')
+    @handler(u'Get information about a host')
     def get(self, name):
         r"get(name) -> Host :: List all the information of a host."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         return self.hosts[name]
 
     def get(self, name):
         r"get(name) -> Host :: List all the information of a host."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         return self.hosts[name]
 
-    @handler(u'List hosts.')
+    @handler(u'List hosts')
     def list(self):
         r"list() -> tuple :: List all the hostnames."
         return self.hosts.keys()
 
     def list(self):
         r"list() -> tuple :: List all the hostnames."
         return self.hosts.keys()
 
-    @handler(u'Get information about all hosts.')
+    @handler(u'Get information about all hosts')
     def show(self):
         r"show() -> list of Hosts :: List all the complete hosts information."
         return self.hosts.values()
     def show(self):
         r"show() -> list of Hosts :: List all the complete hosts information."
         return self.hosts.values()
@@ -148,6 +144,8 @@ class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
     Both defaults to the current working directory.
     """
 
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage DHCP service"
+
     _initd_name = 'dhcpd'
 
     _persistent_attrs = ('params', 'hosts')
     _initd_name = 'dhcpd'
 
     _persistent_attrs = ('params', 'hosts')
index 624dfc44c14e67690a1a59d3572df6d089fdba1f..cf44ea4e4036334ef70747416aaa7500e2056bb4 100644 (file)
@@ -29,13 +29,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class ZoneError(Error, KeyError):
     r"""
 
 class ZoneError(Error, KeyError):
     r"""
@@ -46,7 +40,7 @@ class ZoneError(Error, KeyError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Zone error: "%s"' % zonename
+        self.message = u'Zone error: "%s"' % zonename
 
 class ZoneNotFoundError(ZoneError):
     r"""
 
 class ZoneNotFoundError(ZoneError):
     r"""
@@ -58,7 +52,7 @@ class ZoneNotFoundError(ZoneError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'zone not found: "%s"' % zonename
+        self.message = u'zone not found: "%s"' % zonename
 
 class ZoneAlreadyExistsError(ZoneError):
     r"""
 
 class ZoneAlreadyExistsError(ZoneError):
     r"""
@@ -69,7 +63,7 @@ class ZoneAlreadyExistsError(ZoneError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Zone already exists: "%s"' % zonename
+        self.message = u'Zone already exists: "%s"' % zonename
 
 class HostError(Error, KeyError):
     r"""
 
 class HostError(Error, KeyError):
     r"""
@@ -80,7 +74,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -91,11 +85,11 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
 
 class HostNotFoundError(HostError):
     r"""
-    HostNotFoundError(hostname) -> HostNotFoundError instance
+    HostNotFoundError(hostname) -> HostNotFoundError instance.
 
     This exception is raised when trying to operate on a hostname that doesn't
     exists.
 
     This exception is raised when trying to operate on a hostname that doesn't
     exists.
@@ -103,36 +97,36 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 class MailExchangeError(Error, KeyError):
     r"""
 
 class MailExchangeError(Error, KeyError):
     r"""
-    MailExchangeError(hostname) -> MailExchangeError instance
+    MailExchangeError(hostname) -> MailExchangeError instance.
 
     This is the base exception for all mail exchange related errors.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
 
     This is the base exception for all mail exchange related errors.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Mail Exchange error: "%s"' % mx
+        self.message = u'Mail Exchange error: "%s"' % mx
 
 class MailExchangeAlreadyExistsError(MailExchangeError):
     r"""
 
 class MailExchangeAlreadyExistsError(MailExchangeError):
     r"""
-    MailExchangeAlreadyExistsError(hostname) -> MailExchangeAlreadyExistsError instance
+    MailExchangeAlreadyExistsError(hostname) -> MailExchangeAlreadyExistsError.
 
     This exception is raised when trying to add a mail exchange that already exists.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
 
     This exception is raised when trying to add a mail exchange that already exists.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Mail Exchange already exists: "%s"' % mx
+        self.message = u'Mail Exchange already exists: "%s"' % mx
 
 class MailExchangeNotFoundError(MailExchangeError):
     r"""
 
 class MailExchangeNotFoundError(MailExchangeError):
     r"""
-    MailExchangeNotFoundError(hostname) -> MailExchangeNotFoundError instance
+    MailExchangeNotFoundError(hostname) -> MailExchangeNotFoundError instance.
 
 
-    This exception is raised when trying to operate on a mail exchange that doesn't
-    exists.
+    This exception is raised when trying to operate on a mail exchange that
+    doesn't exists.
     """
 
     def __init__(self, mx):
     """
 
     def __init__(self, mx):
@@ -152,9 +146,10 @@ class NameServerError(Error, KeyError):
 
 class NameServerAlreadyExistsError(NameServerError):
     r"""
 
 class NameServerAlreadyExistsError(NameServerError):
     r"""
-    NameServerAlreadyExistsError(hostname) -> NameServerAlreadyExistsError instance
+    NameServerAlreadyExistsError(hostname) -> NameServerAlreadyExistsError.
 
 
-    This exception is raised when trying to add a name server that already exists.
+    This exception is raised when trying to add a name server that already
+    exists.
     """
 
     def __init__(self, ns):
     """
 
     def __init__(self, ns):
@@ -163,10 +158,10 @@ class NameServerAlreadyExistsError(NameServerError):
 
 class NameServerNotFoundError(NameServerError):
     r"""
 
 class NameServerNotFoundError(NameServerError):
     r"""
-    NameServerNotFoundError(hostname) -> NameServerNotFoundError instance
+    NameServerNotFoundError(hostname) -> NameServerNotFoundError instance.
 
 
-    This exception is raised when trying to operate on a name server that doesn't
-    exists.
+    This exception is raised when trying to operate on a name server that
+    doesn't exists.
     """
 
     def __init__(self, ns):
     """
 
     def __init__(self, ns):
@@ -183,6 +178,9 @@ class Host(Sequence):
         return (self.name, self.ip)
 
 class HostHandler(Handler):
         return (self.name, self.ip)
 
 class HostHandler(Handler):
+
+    handler_help = u"Manage DNS hosts"
+
     def __init__(self,zones):
         self.zones = zones
 
     def __init__(self,zones):
         self.zones = zones
 
@@ -233,6 +231,8 @@ class MailExchange(Sequence):
 
 class MailExchangeHandler(Handler):
 
 
 class MailExchangeHandler(Handler):
 
+    handler_help = u"Manage DNS mail exchangers (MX)"
+
     def __init__(self, zones):
         self.zones = zones
 
     def __init__(self, zones):
         self.zones = zones
 
@@ -282,6 +282,8 @@ class NameServer(Sequence):
 
 class NameServerHandler(Handler):
 
 
 class NameServerHandler(Handler):
 
+    handler_help = u"Manage DNS name servers (NS)"
+
     def __init__(self, zones):
         self.zones = zones
 
     def __init__(self, zones):
         self.zones = zones
 
@@ -326,7 +328,6 @@ class Zone(Sequence):
         return (self.name, self.hosts, self.mxs, self.nss)
 
 class ZoneHandler(Handler):
         return (self.name, self.hosts, self.mxs, self.nss)
 
 class ZoneHandler(Handler):
-
     r"""ZoneHandler(zones) -> ZoneHandler instance :: Handle a list of zones.
 
     This class is a helper for DnsHandler to do all the work related to zone
     r"""ZoneHandler(zones) -> ZoneHandler instance :: Handle a list of zones.
 
     This class is a helper for DnsHandler to do all the work related to zone
@@ -334,6 +335,9 @@ class ZoneHandler(Handler):
 
     zones - A dictionary with string keys (zone name) and Zone instances values.
     """
 
     zones - A dictionary with string keys (zone name) and Zone instances values.
     """
+
+    handler_help = u"Manage DNS zones"
+
     def __init__(self, zones):
         self.zones = zones
 
     def __init__(self, zones):
         self.zones = zones
 
@@ -378,6 +382,8 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
     Both defaults to the current working directory.
     """
 
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage DNS service"
+
     _initd_name = 'bind'
 
     _persistent_attrs = ('params', 'zones')
     _initd_name = 'bind'
 
     _persistent_attrs = ('params', 'zones')
index dbf9b155015e4053cc32cc83e96c2537d18dec09..229cc207a3a2a5efff14b7d2f1e59bc02fb3bab8 100644 (file)
@@ -22,13 +22,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class RuleError(Error, KeyError):
     r"""
 
 class RuleError(Error, KeyError):
     r"""
@@ -39,7 +33,7 @@ class RuleError(Error, KeyError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule error: "%s"' % rule
+        self.message = u'Rule error: "%s"' % rule
 
 class RuleAlreadyExistsError(RuleError):
     r"""
 
 class RuleAlreadyExistsError(RuleError):
     r"""
@@ -50,7 +44,7 @@ class RuleAlreadyExistsError(RuleError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule already exists: "%s"' % rule
+        self.message = u'Rule already exists: "%s"' % rule
 
 class RuleNotFoundError(RuleError):
     r"""
 
 class RuleNotFoundError(RuleError):
     r"""
@@ -62,7 +56,7 @@ class RuleNotFoundError(RuleError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule not found: "%s"' % rule
+        self.message = u'Rule not found: "%s"' % rule
 
 
 class Rule(Sequence):
 
 
 class Rule(Sequence):
@@ -129,11 +123,13 @@ class RuleHandler(Handler):
     rules - A list of Rule objects.
     """
 
     rules - A list of Rule objects.
     """
 
+    handler_help = u"Manage firewall rules"
+
     def __init__(self, rules):
         r"Initialize the object, see class documentation for details."
         self.rules = rules
 
     def __init__(self, rules):
         r"Initialize the object, see class documentation for details."
         self.rules = rules
 
-    @handler(u'Add a new rule.')
+    @handler(u'Add a new rule')
     def add(self, *args, **kwargs):
         r"add(rule) -> None :: Add a rule to the rules list (see Rule doc)."
         rule = Rule(*args, **kwargs)
     def add(self, *args, **kwargs):
         r"add(rule) -> None :: Add a rule to the rules list (see Rule doc)."
         rule = Rule(*args, **kwargs)
@@ -141,7 +137,7 @@ class RuleHandler(Handler):
             raise RuleAlreadyExistsError(rule)
         self.rules.append(rule)
 
             raise RuleAlreadyExistsError(rule)
         self.rules.append(rule)
 
-    @handler(u'Update a rule.')
+    @handler(u'Update a rule')
     def update(self, index, *args, **kwargs):
         r"update(index, rule) -> None :: Update a rule (see Rule doc)."
         # TODO check if the modified rule is the same of an existing one
     def update(self, index, *args, **kwargs):
         r"update(index, rule) -> None :: Update a rule (see Rule doc)."
         # TODO check if the modified rule is the same of an existing one
@@ -151,7 +147,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Delete a rule.')
+    @handler(u'Delete a rule')
     def delete(self, index):
         r"delete(index) -> Rule :: Delete a rule from the list returning it."
         index = int(index) # TODO validation
     def delete(self, index):
         r"delete(index) -> Rule :: Delete a rule from the list returning it."
         index = int(index) # TODO validation
@@ -160,7 +156,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Get information about a rule.')
+    @handler(u'Get information about a rule')
     def get(self, index):
         r"get(rule) -> Rule :: Get all the information about a rule."
         index = int(index) # TODO validation
     def get(self, index):
         r"get(rule) -> Rule :: Get all the information about a rule."
         index = int(index) # TODO validation
@@ -169,7 +165,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Get information about all rules.')
+    @handler(u'Get information about all rules')
     def show(self):
         r"show() -> list of Rules :: List all the complete rules information."
         return self.rules
     def show(self):
         r"show() -> list of Rules :: List all the complete rules information."
         return self.rules
@@ -188,6 +184,8 @@ class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
     Both defaults to the current working directory.
     """
 
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage firewall service"
+
     _persistent_attrs = 'rules'
 
     _restorable_defaults = dict(rules=list())
     _persistent_attrs = 'rules'
 
     _restorable_defaults = dict(rules=list())
index 4330eeb359b8cdb8a31d49295505c07a69d9d911..c512d26a46bf0766c89416887e4795998330af51 100644 (file)
@@ -21,53 +21,47 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class DeviceError(Error):
 
     def __init__(self, device):
 
 class DeviceError(Error):
 
     def __init__(self, device):
-        self.message = 'Device error : "%s"' % device
+        self.message = u'Device error : "%s"' % device
 
 class DeviceNotFoundError(DeviceError):
 
     def __init__(self, device):
 
 class DeviceNotFoundError(DeviceError):
 
     def __init__(self, device):
-        self.message = 'Device not found : "%s"' % device
+        self.message = u'Device not found : "%s"' % device
 
 class AddressError(Error):
 
     def __init__(self, addr):
 
 class AddressError(Error):
 
     def __init__(self, addr):
-        self.message = 'Address error : "%s"' % addr
+        self.message = u'Address error : "%s"' % addr
 
 class AddressNotFoundError(AddressError):
 
     def __init__(self, address):
 
 class AddressNotFoundError(AddressError):
 
     def __init__(self, address):
-        self.message = 'Address not found : "%s"' % address
+        self.message = u'Address not found : "%s"' % address
 
 class AddressAlreadyExistsError(AddressError):
 
     def __init__(self, address):
 
 class AddressAlreadyExistsError(AddressError):
 
     def __init__(self, address):
-        self.message = 'Address already exists : "%s"' % address
+        self.message = u'Address already exists : "%s"' % address
 
 class RouteError(Error):
 
     def __init__(self, route):
 
 class RouteError(Error):
 
     def __init__(self, route):
-        self.message = 'Route error : "%s"' % route
+        self.message = u'Route error : "%s"' % route
 
 class RouteNotFoundError(RouteError):
 
     def __init__(self, route):
 
 class RouteNotFoundError(RouteError):
 
     def __init__(self, route):
-        self.message = 'Route not found : "%s"' % route
+        self.message = u'Route not found : "%s"' % route
 
 class RouteAlreadyExistsError(RouteError):
 
     def __init__(self, route):
 
 class RouteAlreadyExistsError(RouteError):
 
     def __init__(self, route):
-        self.message = 'Route already exists : "%s"' % route
+        self.message = u'Route already exists : "%s"' % route
 
 
 class Route(Sequence):
 
 
 class Route(Sequence):
@@ -89,6 +83,8 @@ class Route(Sequence):
 
 class RouteHandler(Handler):
 
 
 class RouteHandler(Handler):
 
+    handler_help = u"Manage IP routes"
+
     def __init__(self, devices):
         self.devices = devices
 
     def __init__(self, devices):
         self.devices = devices
 
@@ -149,6 +145,8 @@ class Address(Sequence):
 
 class AddressHandler(Handler):
 
 
 class AddressHandler(Handler):
 
+    handler_help = u"Manage IP addresses"
+
     def __init__(self, devices):
         self.devices = devices
 
     def __init__(self, devices):
         self.devices = devices
 
@@ -204,6 +202,8 @@ class Device(Sequence):
 
 class DeviceHandler(Handler):
 
 
 class DeviceHandler(Handler):
 
+    handler_help = u"Manage network devices"
+
     def __init__(self, devices):
         # FIXME remove templates to execute commands
         from mako.template import Template
     def __init__(self, devices):
         # FIXME remove templates to execute commands
         from mako.template import Template
@@ -251,6 +251,8 @@ def get_devices():
 
 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
 
 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
+    handler_help = u"Manage IP devices, addresses and routes"
+
     _persistent_attrs = 'devices'
 
     _restorable_defaults = dict(devices=get_devices())
     _persistent_attrs = 'devices'
 
     _restorable_defaults = dict(devices=get_devices())
index b3b1172bc74474752890f5ccd48fd8f2fd32ec6a..399eba1bf341b5c9eb37bcad32d9738ff572dd48 100644 (file)
@@ -19,13 +19,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class HostError(Error, KeyError):
     r"""
 
 class HostError(Error, KeyError):
     r"""
@@ -36,7 +30,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -47,7 +41,7 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
 
 class HostNotFoundError(HostError):
     r"""
@@ -59,7 +53,7 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 
 class Host(Sequence):
 
 
 class Host(Sequence):
@@ -72,6 +66,8 @@ class Host(Sequence):
 
 class HostHandler(Handler):
 
 
 class HostHandler(Handler):
 
+    handler_help = u"Manage proxy hosts"
+
     def __init__(self, hosts):
         self.hosts = hosts
 
     def __init__(self, hosts):
         self.hosts = hosts
 
@@ -99,6 +95,8 @@ class HostHandler(Handler):
 class ProxyHandler(Restorable, ConfigWriter, InitdHandler,
                    TransactionalHandler, ParametersHandler):
 
 class ProxyHandler(Restorable, ConfigWriter, InitdHandler,
                    TransactionalHandler, ParametersHandler):
 
+    handler_help = u"Manage proxy service"
+
     _initd_name = 'squid'
 
     _persistent_attrs = ('params', 'hosts')
     _initd_name = 'squid'
 
     _persistent_attrs = ('params', 'hosts')