new system to load backends

Now there is a single file ~/.weboob/backends, where every backends are
instancied. There are two ways to create backends for frontends:
- Use Weboob.load_backends(), to load every backends in the config file
- Use Weboob.load_modules(), to instanciate every module one time
This commit is contained in:
Romain Bignon 2010-04-01 20:01:01 +02:00
commit e119a70cec
9 changed files with 102 additions and 28 deletions

View file

@ -18,15 +18,50 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""
import re
class Backend:
# Module name.
NAME = None
# Name of the maintainer of this module.
MAINTAINER = '<unspecifier>'
# Email address of the maintainer.
EMAIL = '<unspecified>'
# Version of module (for information only).
VERSION = '<unspecified>'
# License of this module.
LICENSE = '<unspecified>'
# Configuration required for this module. # Values must be ConfigField
# objects.
CONFIG = {}
class ConfigField(object):
def __init__(self, default=None, is_masked=False, regexp=None, description=None):
self.default = default
self.is_masked = is_masked
self.regexp = regexp
self.description = description
class ConfigError(Exception): pass
def __init__(self, weboob, config):
self.weboob = weboob
self.config = config
self.config = {}
for name, field in self.CONFIG.iteritems():
value = config.get(name, field.default)
if value is None:
raise Backend.ConfigError("Missing parameter '%s'" % name)
if field.regexp and re.match(field.regexp, str(value)):
raise Backend.ConfigError("Value of '%s' does not match regexp '%s'" % (name, field.regexp))
if not field.default is None:
if isinstance(field.default, int):
value = int(value)
if isinstance(field.default, float):
value = float(value)
self.config[name] = value
def has_caps(self, *caps):
for c in caps:

View file

@ -22,6 +22,7 @@ from weboob.backend import Backend
from weboob.capabilities.messages import ICapMessages, ICapMessagesReply
class AuMBackend(Backend, ICapMessages, ICapMessagesReply):
NAME = 'aum'
MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@peerfuse.org'
VERSION = '1.0'

View file

@ -24,6 +24,7 @@ from weboob.capabilities.travel import ICapTravel, Station, Departure
from .browser import CanalTP
class CanalTPBackend(Backend, ICapTravel):
NAME = 'canaltp'
MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@peerfuse.org'
VERSION = '1.0'

View file

@ -24,10 +24,14 @@ from weboob.capabilities.updatable import ICapUpdatable
from feeds import ArticlesList
class DLFPBackend(Backend, ICapMessages, ICapMessagesReply, ICapUpdatable):
NAME = 'dlfp'
MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@peerfuse.org'
VERSION = '1.0'
LICENSE = 'GPLv3'
CONFIG = {'username': Backend.ConfigField(description='Username on website'),
'password': Backend.ConfigField(description='Password of account', is_masked=True)
}
def iter_messages(self):
articles_list = ArticlesList('newspaper')

View file

@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from logging import warning
import feedparser
import re
import datetime
from datetime import datetime
class Article:
RSS = None

View file

@ -25,6 +25,7 @@ from .browser import Transilien
from .stations import STATIONS
class TransilienBackend(Backend, ICapTravel):
NAME = 'transilien'
MAINTAINER = u'Julien Hébert'
EMAIL = 'juke@free.fr'
VERSION = '1.0'

View file

@ -28,7 +28,7 @@ class Application(BaseApplication):
APPNAME = 'dummy'
def main(self, argv):
self.weboob.load_modules()
self.weboob.load_backends()
for name, backend in self.weboob.iter_backends():
print '= Processing backend name = %s' % name

View file

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import re
import os
from ConfigParser import SafeConfigParser
from logging import warning, debug
from types import ClassType
@ -39,6 +40,9 @@ class Module:
if not self.klass:
raise ImportError("This is not a backend module (no Backend class found)")
def get_name(self):
return self.klass.NAME
def has_caps(self, *caps):
for c in caps:
if issubclass(self.klass, c):
@ -62,12 +66,47 @@ class ModulesLoader:
def load_module(self, name):
try:
backend = Module(name, __import__(name, fromlist=[name]))
module = Module(name, __import__(name, fromlist=[name]))
except ImportError, e:
warning('Unable to load module %s: %s' % (name, e))
return
if name in self.modules:
warning('Module "%s" is already loaded (%s)' % self.modules[name].module)
return
self.modules[name] = backend
debug('Loaded module %s (%s)' % (name, backend.module.__name__))
self.modules[module.get_name()] = module
debug('Loaded module %s (%s)' % (name, module.module.__name__))
def load_backends(self, confpath, caps, names):
config = SafeConfigParser()
config.read(confpath)
backends = {}
for name in config.sections():
params = dict(config.items(name))
try:
module = self.modules[params['_type']]
except KeyError:
warning('Unable to find module %s', name)
continue
# Check conditions
if (not caps is None and not module.has_caps(caps)) or \
(not names is None and not module.name in name):
continue
try:
backends[name] = module.create_backend(self, params)
except Exception, e:
warning('Unable to load %s backend: %s' % (name, e))
return backends
def load_modules_as_backends(self, caps, names):
backends = {}
for name, module in self.modules.iteritems():
if (caps is None or module.has_caps(caps)) and \
(names is None or module.name in names):
try:
backends[module.name] = module.create_backend(self, {})
except Exception, e:
warning('Unable to load %s backend: %s' % (name, e))
return backends

View file

@ -18,40 +18,33 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""
import os
import sched
import time
from weboob.modules import ModulesLoader
class Weboob:
def __init__(self, app_name):
WORKDIR = os.path.join(os.path.expanduser('~'), '.weboob')
BACKENDS_FILENAME = 'backends'
def __init__(self, app_name, workdir=WORKDIR):
self.app_name = app_name
self.workdir = workdir
self.backends = {}
self.scheduler = sched.scheduler(time.time, time.sleep)
self.modules_loader = ModulesLoader()
self.modules_loader.load()
def load_modules(self, caps=None, name=None, backends=None):
if backends is None:
for name, module in self.modules_loader.modules.iteritems():
if (not caps or module.has_caps(caps)) and \
(not name or module.name == name):
backend = module.create_backend(self, None)
self.backends[module.name] = backend
else:
for key, backendcfg in backends.iteritems():
try:
module = self.modules_loader[backendcfg.type]
except KeyError:
continue
if (caps and not module.has_caps(caps)) or \
(name and module.name != name):
continue
self.backends[backendcfg.name] = module.create_backend(self, backendcfg)
def get_backends_filename(self):
return os.path.join(self.workdir, self.BACKENDS_FILENAME)
def load_module(self, modname, instname, backendcfg=None):
module = self.modules_loader[modname]
self.backends[instname] = module.create_backend(self, backendcfg)
def load_backends(self, caps=None, names=None):
self.backends.update(self.modules_loader.load_backends(self.get_backends_filename(), caps, names))
def load_modules(self, caps=None, names=None):
self.backends.update(self.modules_loader.load_modules_as_backends(caps, names))
def iter_backends(self, caps=None):
for name, backend in self.backends.iteritems():