From: Leandro Lucarella Date: Sat, 6 Oct 2007 04:02:35 +0000 (-0300) Subject: Improve a lot error reporting and unicode/utf-8 compatibility. X-Git-Url: https://git.llucax.com/software/pymin.git/commitdiff_plain/7d2f3da6aee023c991c9669a6a4664bd8be53a97?hp=--cc Improve a lot error reporting and unicode/utf-8 compatibility. 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. --- 7d2f3da6aee023c991c9669a6a4664bd8be53a97 diff --git a/TODO b/TODO index 362b434..b8d9c03 100644 --- a/TODO +++ b/TODO @@ -1,19 +1,6 @@ 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. diff --git a/pymin/dispatcher.py b/pymin/dispatcher.py index 7e9ef60..39b4b75 100644 --- a/pymin/dispatcher.py +++ b/pymin/dispatcher.py @@ -19,7 +19,16 @@ class Error(RuntimeError): 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. @@ -37,25 +46,59 @@ class CommandError(Error): """ 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 - 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): - 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. """ - 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 @@ -75,8 +118,26 @@ class ParseError(CommandError): 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. @@ -88,33 +149,32 @@ def handler(help): 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 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 - 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))) - @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. @@ -123,14 +183,19 @@ class Handler: 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. @@ -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. - 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): @@ -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 - "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. + + route - *unicode* string with the command 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: + if isinstance(handler, Handler): + raise CommandIsAHandlerError(command) 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) - handler = getattr(handler, route[0]) + handler = getattr(handler, route[0].encode('utf-8')) 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): - @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): - @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 - @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() @@ -388,7 +457,7 @@ if __name__ == '__main__': 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') @@ -396,7 +465,11 @@ if __name__ == '__main__': 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 diff --git a/pymin/pymindaemon.py b/pymin/pymindaemon.py index ee5f805..f749753 100644 --- a/pymin/pymindaemon.py +++ b/pymin/pymindaemon.py @@ -49,6 +49,7 @@ class PyminDaemon(eventloop.EventLoop): # Create EventLoop eventloop.EventLoop.__init__(self, sock) # Create Dispatcher + #TODO root.pymin = PyminHandler() 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: - 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 ' @@ -81,7 +82,7 @@ class PyminDaemon(eventloop.EventLoop): 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())" diff --git a/pymin/services/dhcp/__init__.py b/pymin/services/dhcp/__init__.py index 8f42e1a..0dcb0d4 100644 --- a/pymin/services/dhcp/__init__.py +++ b/pymin/services/dhcp/__init__.py @@ -19,13 +19,7 @@ class Error(HandlerError): 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""" @@ -36,7 +30,7 @@ class HostError(Error, KeyError): 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""" @@ -47,7 +41,7 @@ class HostAlreadyExistsError(HostError): 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""" @@ -59,7 +53,7 @@ class HostNotFoundError(HostError): 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): @@ -89,18 +83,20 @@ class HostHandler(Handler): 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 - @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) - @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: @@ -110,26 +106,26 @@ class HostHandler(Handler): 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] - @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] - @handler(u'List hosts.') + @handler(u'List hosts') 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() @@ -148,6 +144,8 @@ class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler, Both defaults to the current working directory. """ + handler_help = u"Manage DHCP service" + _initd_name = 'dhcpd' _persistent_attrs = ('params', 'hosts') diff --git a/pymin/services/dns/__init__.py b/pymin/services/dns/__init__.py index 624dfc4..cf44ea4 100644 --- a/pymin/services/dns/__init__.py +++ b/pymin/services/dns/__init__.py @@ -29,13 +29,7 @@ class Error(HandlerError): 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""" @@ -46,7 +40,7 @@ class ZoneError(Error, KeyError): 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""" @@ -58,7 +52,7 @@ class ZoneNotFoundError(ZoneError): 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""" @@ -69,7 +63,7 @@ class ZoneAlreadyExistsError(ZoneError): 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""" @@ -80,7 +74,7 @@ class HostError(Error, KeyError): 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""" @@ -91,11 +85,11 @@ class HostAlreadyExistsError(HostError): 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""" - HostNotFoundError(hostname) -> HostNotFoundError instance + HostNotFoundError(hostname) -> HostNotFoundError instance. 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." - self.message = 'Host not found: "%s"' % hostname + self.message = u'Host not found: "%s"' % hostname 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." - self.message = 'Mail Exchange error: "%s"' % mx + self.message = u'Mail Exchange error: "%s"' % mx 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." - self.message = 'Mail Exchange already exists: "%s"' % mx + self.message = u'Mail Exchange already exists: "%s"' % mx 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): @@ -152,9 +146,10 @@ class NameServerError(Error, KeyError): 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): @@ -163,10 +158,10 @@ class NameServerAlreadyExistsError(NameServerError): 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): @@ -183,6 +178,9 @@ class Host(Sequence): return (self.name, self.ip) class HostHandler(Handler): + + handler_help = u"Manage DNS hosts" + def __init__(self,zones): self.zones = zones @@ -233,6 +231,8 @@ class MailExchange(Sequence): class MailExchangeHandler(Handler): + handler_help = u"Manage DNS mail exchangers (MX)" + def __init__(self, zones): self.zones = zones @@ -282,6 +282,8 @@ class NameServer(Sequence): class NameServerHandler(Handler): + handler_help = u"Manage DNS name servers (NS)" + 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): - 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. """ + + handler_help = u"Manage DNS 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. """ + handler_help = u"Manage DNS service" + _initd_name = 'bind' _persistent_attrs = ('params', 'zones') diff --git a/pymin/services/firewall/__init__.py b/pymin/services/firewall/__init__.py index dbf9b15..229cc20 100644 --- a/pymin/services/firewall/__init__.py +++ b/pymin/services/firewall/__init__.py @@ -22,13 +22,7 @@ class Error(HandlerError): 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""" @@ -39,7 +33,7 @@ class RuleError(Error, KeyError): 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""" @@ -50,7 +44,7 @@ class RuleAlreadyExistsError(RuleError): 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""" @@ -62,7 +56,7 @@ class RuleNotFoundError(RuleError): 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): @@ -129,11 +123,13 @@ class RuleHandler(Handler): 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 - @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) @@ -141,7 +137,7 @@ class RuleHandler(Handler): 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 @@ -151,7 +147,7 @@ class RuleHandler(Handler): 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 @@ -160,7 +156,7 @@ class RuleHandler(Handler): 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 @@ -169,7 +165,7 @@ class RuleHandler(Handler): 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 @@ -188,6 +184,8 @@ class FirewallHandler(Restorable, ConfigWriter, ServiceHandler, Both defaults to the current working directory. """ + handler_help = u"Manage firewall service" + _persistent_attrs = 'rules' _restorable_defaults = dict(rules=list()) diff --git a/pymin/services/ip/__init__.py b/pymin/services/ip/__init__.py index 4330eeb..c512d26 100644 --- a/pymin/services/ip/__init__.py +++ b/pymin/services/ip/__init__.py @@ -21,53 +21,47 @@ class Error(HandlerError): 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): - self.message = 'Device error : "%s"' % device + self.message = u'Device error : "%s"' % 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): - self.message = 'Address error : "%s"' % addr + self.message = u'Address error : "%s"' % addr 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): - self.message = 'Address already exists : "%s"' % address + self.message = u'Address already exists : "%s"' % address 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): - self.message = 'Route not found : "%s"' % route + self.message = u'Route not found : "%s"' % 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): @@ -89,6 +83,8 @@ class Route(Sequence): class RouteHandler(Handler): + handler_help = u"Manage IP routes" + def __init__(self, devices): self.devices = devices @@ -149,6 +145,8 @@ class Address(Sequence): class AddressHandler(Handler): + handler_help = u"Manage IP addresses" + def __init__(self, devices): self.devices = devices @@ -204,6 +202,8 @@ class Device(Sequence): class DeviceHandler(Handler): + handler_help = u"Manage network devices" + 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): + handler_help = u"Manage IP devices, addresses and routes" + _persistent_attrs = 'devices' _restorable_defaults = dict(devices=get_devices()) diff --git a/pymin/services/proxy/__init__.py b/pymin/services/proxy/__init__.py index b3b1172..399eba1 100644 --- a/pymin/services/proxy/__init__.py +++ b/pymin/services/proxy/__init__.py @@ -19,13 +19,7 @@ class Error(HandlerError): 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""" @@ -36,7 +30,7 @@ class HostError(Error, KeyError): 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""" @@ -47,7 +41,7 @@ class HostAlreadyExistsError(HostError): 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""" @@ -59,7 +53,7 @@ class HostNotFoundError(HostError): 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): @@ -72,6 +66,8 @@ class Host(Sequence): class HostHandler(Handler): + handler_help = u"Manage proxy hosts" + def __init__(self, hosts): self.hosts = hosts @@ -99,6 +95,8 @@ class HostHandler(Handler): class ProxyHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler, ParametersHandler): + handler_help = u"Manage proxy service" + _initd_name = 'squid' _persistent_attrs = ('params', 'hosts')