From 0435cd7411a59a54e4302fec5652ba48da92fcc3 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sat, 10 Jul 2010 14:34:28 +0200 Subject: [PATCH] comments --- weboob/tools/application/base.py | 71 ++++++++++++++++++++--------- weboob/tools/application/console.py | 8 +++- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/weboob/tools/application/base.py b/weboob/tools/application/base.py index 2a53dd0d..8478106e 100644 --- a/weboob/tools/application/base.py +++ b/weboob/tools/application/base.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright(C) 2010 Romain Bignon +# Copyright(C) 2010 Romain Bignon, Christophe Benz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -56,14 +56,23 @@ class ApplicationStorage(object): return self.storage.save('applications', self.name) class BaseApplication(object): + """ + Base application. + + This class can be herited to have some common code within weboob + applications. + """ + + # ------ Class attributes -------------------------------------- + # Application name APPNAME = '' - # Default configuration - CONFIG = {} - # Default storage - STORAGE = {} - # Configuration directory + # Configuration and work directory (default: ~/.weboob/) CONFDIR = os.path.join(os.path.expanduser('~'), '.weboob') + # Default configuration dict (can only contain key/values) + CONFIG = {} + # Default storage tree + STORAGE = {} # Synopsis SYNOPSIS = 'Usage: %prog [options (-h for help)] ...' # Version @@ -71,6 +80,25 @@ class BaseApplication(object): # Copyright COPYRIGHT = None + # ------ Abstract methods -------------------------------------- + def create_weboob(self): + return Weboob() + + def _get_completions(self): + """ + Overload this method in subclasses if you want to enrich shell completion. + @return a set object + """ + return set() + + def _handle_app_options(self): + """ + Overload this method in subclasses if you want to handle options defined in subclass constructor. + """ + pass + + # ------ BaseApplication methods ------------------------------- + def __init__(self, option_parser=None): self.weboob = self.create_weboob() self.config = None @@ -86,9 +114,6 @@ class BaseApplication(object): self._parser.add_option_group(logging_options) self._parser.add_option('--shell-completion', action='store_true', help=optparse.SUPPRESS_HELP) - def create_weboob(self): - return Weboob() - def create_storage(self, path=None, klass=None): """ Create a storage object. @@ -151,13 +176,6 @@ class BaseApplication(object): logging.warning(u'No configured backend loaded') return loaded - def _get_completions(self): - """ - Overload this method in subclasses if you want to enrich shell completion. - @return a set object - """ - return set() - def _get_optparse_version(self): version = None if self.VERSION: @@ -167,14 +185,22 @@ class BaseApplication(object): version = '%s v%s' % (self.APPNAME, self.VERSION) return version - def _handle_app_options(self): - """ - Overload this method in subclasses if you want to handle options defined in subclass constructor. - """ - pass - @classmethod def run(klass, args=None): + """ + This static method can be called to run the application. + + It creates the application object, handle options, setup logging, run + the main() method, and catch common exceptions. + + You can't do anything after this call, as it *always* finish with + a call to sys.exit(). + + For example: + >>> from weboob.application.myapplication import MyApplication + >>> MyApplication.run() + """ + if args is None: args = [(sys.stdin.encoding and arg.decode(sys.stdin.encoding) or arg) for arg in sys.argv] app = klass() @@ -207,6 +233,7 @@ class BaseApplication(object): sys.exit(app.main(args)) except KeyboardInterrupt: print 'Program killed by SIGINT' + sys.exit(0) # XXX is it really the right exit code? -romain except ConfigError, e: print 'Configuration error: %s' % e sys.exit(1) diff --git a/weboob/tools/application/console.py b/weboob/tools/application/console.py index 4d78ec0b..0c73d999 100644 --- a/weboob/tools/application/console.py +++ b/weboob/tools/application/console.py @@ -35,6 +35,10 @@ __all__ = ['ConsoleApplication'] class ConsoleApplication(BaseApplication): + """ + Base application class for CLI applications. + """ + SYNOPSIS = 'Usage: %prog [options (-h for help)] command [parameters...]' def __init__(self): @@ -70,6 +74,7 @@ class ConsoleApplication(BaseApplication): self._parser.add_option_group(formatting_options) def add_application_options(self, group): + # XXX why is it in ConsoleApplication and not BaseApplication? -romain pass def _handle_app_options(self): @@ -200,7 +205,7 @@ class ConsoleApplication(BaseApplication): if varargs: args.append("[%s..]" % varargs) if varkw: - args.append("{WTF}" % varkw) + raise TypeError('Command %s requests illegal keyword args (**%s)' % varkw) return " ".join(args) command_name = f.func_name.replace('command_', '') @@ -230,6 +235,7 @@ class ConsoleApplication(BaseApplication): except ResultsConditionException, e: logging.error(e) + # XXX why do not use staticmethod as a decorator? -romain register_command = staticmethod(register_command) command = staticmethod(command)