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:
parent
bc567a2208
commit
e119a70cec
9 changed files with 102 additions and 28 deletions
|
|
@ -18,15 +18,50 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
class Backend:
|
class Backend:
|
||||||
|
# Module name.
|
||||||
|
NAME = None
|
||||||
|
# Name of the maintainer of this module.
|
||||||
MAINTAINER = '<unspecifier>'
|
MAINTAINER = '<unspecifier>'
|
||||||
|
# Email address of the maintainer.
|
||||||
EMAIL = '<unspecified>'
|
EMAIL = '<unspecified>'
|
||||||
|
# Version of module (for information only).
|
||||||
VERSION = '<unspecified>'
|
VERSION = '<unspecified>'
|
||||||
|
# License of this module.
|
||||||
LICENSE = '<unspecified>'
|
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):
|
def __init__(self, weboob, config):
|
||||||
self.weboob = weboob
|
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):
|
def has_caps(self, *caps):
|
||||||
for c in caps:
|
for c in caps:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from weboob.backend import Backend
|
||||||
from weboob.capabilities.messages import ICapMessages, ICapMessagesReply
|
from weboob.capabilities.messages import ICapMessages, ICapMessagesReply
|
||||||
|
|
||||||
class AuMBackend(Backend, ICapMessages, ICapMessagesReply):
|
class AuMBackend(Backend, ICapMessages, ICapMessagesReply):
|
||||||
|
NAME = 'aum'
|
||||||
MAINTAINER = 'Romain Bignon'
|
MAINTAINER = 'Romain Bignon'
|
||||||
EMAIL = 'romain@peerfuse.org'
|
EMAIL = 'romain@peerfuse.org'
|
||||||
VERSION = '1.0'
|
VERSION = '1.0'
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from weboob.capabilities.travel import ICapTravel, Station, Departure
|
||||||
from .browser import CanalTP
|
from .browser import CanalTP
|
||||||
|
|
||||||
class CanalTPBackend(Backend, ICapTravel):
|
class CanalTPBackend(Backend, ICapTravel):
|
||||||
|
NAME = 'canaltp'
|
||||||
MAINTAINER = 'Romain Bignon'
|
MAINTAINER = 'Romain Bignon'
|
||||||
EMAIL = 'romain@peerfuse.org'
|
EMAIL = 'romain@peerfuse.org'
|
||||||
VERSION = '1.0'
|
VERSION = '1.0'
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,14 @@ from weboob.capabilities.updatable import ICapUpdatable
|
||||||
from feeds import ArticlesList
|
from feeds import ArticlesList
|
||||||
|
|
||||||
class DLFPBackend(Backend, ICapMessages, ICapMessagesReply, ICapUpdatable):
|
class DLFPBackend(Backend, ICapMessages, ICapMessagesReply, ICapUpdatable):
|
||||||
|
NAME = 'dlfp'
|
||||||
MAINTAINER = 'Romain Bignon'
|
MAINTAINER = 'Romain Bignon'
|
||||||
EMAIL = 'romain@peerfuse.org'
|
EMAIL = 'romain@peerfuse.org'
|
||||||
VERSION = '1.0'
|
VERSION = '1.0'
|
||||||
LICENSE = 'GPLv3'
|
LICENSE = 'GPLv3'
|
||||||
|
CONFIG = {'username': Backend.ConfigField(description='Username on website'),
|
||||||
|
'password': Backend.ConfigField(description='Password of account', is_masked=True)
|
||||||
|
}
|
||||||
|
|
||||||
def iter_messages(self):
|
def iter_messages(self):
|
||||||
articles_list = ArticlesList('newspaper')
|
articles_list = ArticlesList('newspaper')
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
from logging import warning
|
from logging import warning
|
||||||
import feedparser
|
import feedparser
|
||||||
import re
|
import re
|
||||||
import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
class Article:
|
class Article:
|
||||||
RSS = None
|
RSS = None
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ from .browser import Transilien
|
||||||
from .stations import STATIONS
|
from .stations import STATIONS
|
||||||
|
|
||||||
class TransilienBackend(Backend, ICapTravel):
|
class TransilienBackend(Backend, ICapTravel):
|
||||||
|
NAME = 'transilien'
|
||||||
MAINTAINER = u'Julien Hébert'
|
MAINTAINER = u'Julien Hébert'
|
||||||
EMAIL = 'juke@free.fr'
|
EMAIL = 'juke@free.fr'
|
||||||
VERSION = '1.0'
|
VERSION = '1.0'
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class Application(BaseApplication):
|
||||||
APPNAME = 'dummy'
|
APPNAME = 'dummy'
|
||||||
|
|
||||||
def main(self, argv):
|
def main(self, argv):
|
||||||
self.weboob.load_modules()
|
self.weboob.load_backends()
|
||||||
|
|
||||||
for name, backend in self.weboob.iter_backends():
|
for name, backend in self.weboob.iter_backends():
|
||||||
print '= Processing backend name = %s' % name
|
print '= Processing backend name = %s' % name
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
from ConfigParser import SafeConfigParser
|
||||||
from logging import warning, debug
|
from logging import warning, debug
|
||||||
from types import ClassType
|
from types import ClassType
|
||||||
|
|
||||||
|
|
@ -39,6 +40,9 @@ class Module:
|
||||||
if not self.klass:
|
if not self.klass:
|
||||||
raise ImportError("This is not a backend module (no Backend class found)")
|
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):
|
def has_caps(self, *caps):
|
||||||
for c in caps:
|
for c in caps:
|
||||||
if issubclass(self.klass, c):
|
if issubclass(self.klass, c):
|
||||||
|
|
@ -62,12 +66,47 @@ class ModulesLoader:
|
||||||
|
|
||||||
def load_module(self, name):
|
def load_module(self, name):
|
||||||
try:
|
try:
|
||||||
backend = Module(name, __import__(name, fromlist=[name]))
|
module = Module(name, __import__(name, fromlist=[name]))
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
warning('Unable to load module %s: %s' % (name, e))
|
warning('Unable to load module %s: %s' % (name, e))
|
||||||
return
|
return
|
||||||
if name in self.modules:
|
if name in self.modules:
|
||||||
warning('Module "%s" is already loaded (%s)' % self.modules[name].module)
|
warning('Module "%s" is already loaded (%s)' % self.modules[name].module)
|
||||||
return
|
return
|
||||||
self.modules[name] = backend
|
self.modules[module.get_name()] = module
|
||||||
debug('Loaded module %s (%s)' % (name, backend.module.__name__))
|
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
|
||||||
|
|
|
||||||
|
|
@ -18,40 +18,33 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import sched
|
import sched
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from weboob.modules import ModulesLoader
|
from weboob.modules import ModulesLoader
|
||||||
|
|
||||||
class Weboob:
|
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.app_name = app_name
|
||||||
|
self.workdir = workdir
|
||||||
self.backends = {}
|
self.backends = {}
|
||||||
self.scheduler = sched.scheduler(time.time, time.sleep)
|
self.scheduler = sched.scheduler(time.time, time.sleep)
|
||||||
|
|
||||||
self.modules_loader = ModulesLoader()
|
self.modules_loader = ModulesLoader()
|
||||||
self.modules_loader.load()
|
self.modules_loader.load()
|
||||||
|
|
||||||
def load_modules(self, caps=None, name=None, backends=None):
|
def get_backends_filename(self):
|
||||||
if backends is None:
|
return os.path.join(self.workdir, self.BACKENDS_FILENAME)
|
||||||
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 load_module(self, modname, instname, backendcfg=None):
|
def load_backends(self, caps=None, names=None):
|
||||||
module = self.modules_loader[modname]
|
self.backends.update(self.modules_loader.load_backends(self.get_backends_filename(), caps, names))
|
||||||
self.backends[instname] = module.create_backend(self, backendcfg)
|
|
||||||
|
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):
|
def iter_backends(self, caps=None):
|
||||||
for name, backend in self.backends.iteritems():
|
for name, backend in self.backends.iteritems():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue