This commit is contained in:
Romain Bignon 2010-07-10 14:34:28 +02:00
commit 0435cd7411
2 changed files with 54 additions and 21 deletions

View file

@ -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)

View file

@ -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)