diff --git a/weboob/applications/boobank/boobank.py b/weboob/applications/boobank/boobank.py
index db36d232c5081302e259f1b0a88cb929e062261d..47393baf6937b0539304066112c7ed522b113718 100644
--- a/weboob/applications/boobank/boobank.py
+++ b/weboob/applications/boobank/boobank.py
@@ -35,7 +35,7 @@ class Boobank(ConsoleApplication):
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
- self.load_backends(ICapBank)
+ self.load_configured_backends(ICapBank)
return self.process_command(*argv[1:])
@ConsoleApplication.command('List every available accounts')
diff --git a/weboob/applications/chatoob/chatoob.py b/weboob/applications/chatoob/chatoob.py
index a110a12af2948f17a575e0b03393e44064c7fa96..f3af85273d37864d2f9004ea7dd55d0a85fa64f1 100644
--- a/weboob/applications/chatoob/chatoob.py
+++ b/weboob/applications/chatoob/chatoob.py
@@ -32,7 +32,7 @@ class Chatoob(ConsoleApplication):
COPYRIGHT = 'Copyright(C) 2010 Christophe Benz'
def main(self, argv):
- self.load_backends(ICapChat)
+ self.load_configured_backends(ICapChat)
#for backend, result in self.weboob.do('start_chat_polling', self.on_new_chat_message):
#logging.info(u'Polling chat messages for backend %s' % backend)
return self.process_command(*argv[1:])
diff --git a/weboob/applications/havesex/havesex.py b/weboob/applications/havesex/havesex.py
index 2a6dad156659aad78c0d943c5eba31f3791b0e87..4c510d705e937b802c3912c189e2052ce4b7cddd 100644
--- a/weboob/applications/havesex/havesex.py
+++ b/weboob/applications/havesex/havesex.py
@@ -38,7 +38,7 @@ class HaveSex(PromptApplication):
def main(self, argv):
self.load_config()
- self.load_backends(ICapDating, storage=self.create_storage(self.STORAGE_FILENAME))
+ self.load_configured_backends(ICapDating, storage=self.create_storage(self.STORAGE_FILENAME))
self.weboob.do('init_optimizations').wait()
diff --git a/weboob/applications/masstransit/masstransit.py b/weboob/applications/masstransit/masstransit.py
index bfd72b6ead3c2922cd464fbad7f273ead7f1f50f..05a5f34a55e16cf219f989a7f5f4116fb834f3e7 100644
--- a/weboob/applications/masstransit/masstransit.py
+++ b/weboob/applications/masstransit/masstransit.py
@@ -233,7 +233,6 @@ class Masstransit(BaseApplication):
COPYRIGHT = 'Copyright(C) 2010 Julien Hébert'
def main(self, argv):
- "main fonction"
- self.load_modules(ICapTravel)
+ self.load_backends(ICapTravel)
MasstransitHildon(self.weboob)
gtk.main()
diff --git a/weboob/applications/monboob/monboob.py b/weboob/applications/monboob/monboob.py
index 3876ec6fc5a446b66f1195a202d8f89a4ada8cc0..4786f8c32462b69a0cdf34868c1b97699e76e3a1 100644
--- a/weboob/applications/monboob/monboob.py
+++ b/weboob/applications/monboob/monboob.py
@@ -93,7 +93,7 @@ def create_weboob(self):
def main(self, argv):
self.load_config()
- self.load_backends(ICapMessages, storage=self.create_storage())
+ self.load_configured_backends(ICapMessages, storage=self.create_storage())
return self.process_command(*argv[1:])
diff --git a/weboob/applications/qboobmsg/main_window.py b/weboob/applications/qboobmsg/main_window.py
index 8b7d56af0d5a2b75fd969705aa947c4c6d11bbfd..9eeee2c4fd731fd50c19faeb8c8ae4ccc8466d7b 100644
--- a/weboob/applications/qboobmsg/main_window.py
+++ b/weboob/applications/qboobmsg/main_window.py
@@ -36,10 +36,10 @@ def __init__(self, config, weboob, parent=None):
self.setCentralWidget(self.manager)
- self.connect(self.ui.actionModules, SIGNAL("triggered()"), self.modulesConfig)
+ self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
self.connect(self.ui.actionRefresh, SIGNAL("triggered()"), self.refresh)
- def modulesConfig(self):
+ def backendsConfig(self):
bckndcfg = BackendCfg(self.weboob, (ICapMessages,), self)
bckndcfg.show()
diff --git a/weboob/applications/qboobmsg/qboobmsg.py b/weboob/applications/qboobmsg/qboobmsg.py
index 732f29a110516236c425c89e381ab9db11071afe..0c0510e2b138905d17536d358fc8e33f46053dd2 100644
--- a/weboob/applications/qboobmsg/qboobmsg.py
+++ b/weboob/applications/qboobmsg/qboobmsg.py
@@ -27,7 +27,7 @@ class QBoobMsg(QtApplication):
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
- self.load_backends(ICapMessages, storage=self.create_storage())
+ self.load_configured_backends(ICapMessages, storage=self.create_storage())
self.main_window = MainWindow(self.config, self.weboob)
self.main_window.show()
diff --git a/weboob/applications/qboobmsg/ui/main_window.ui b/weboob/applications/qboobmsg/ui/main_window.ui
index 330e9460dcfd557badbec1203dc3ae5a688b4b44..f40742b6d79c77973a087526d68282498e94d337 100644
--- a/weboob/applications/qboobmsg/ui/main_window.ui
+++ b/weboob/applications/qboobmsg/ui/main_window.ui
@@ -29,7 +29,7 @@
File
-
+
@@ -47,12 +47,12 @@
false
-
+
-
+
- Modules
+ Backends
diff --git a/weboob/applications/qhavesex/main_window.py b/weboob/applications/qhavesex/main_window.py
index 276d694808627e982a43f9d0680633766899feb5..db595c93df96d1f8a8561872f8a4ab2481ff22f0 100644
--- a/weboob/applications/qhavesex/main_window.py
+++ b/weboob/applications/qhavesex/main_window.py
@@ -44,10 +44,10 @@ def __init__(self, config, weboob, parent=None):
self.ui.tabWidget.addTab(ContactsWidget(self.weboob), self.tr('Contacts'))
self.ui.tabWidget.addTab(QWidget(), self.tr('Calendar'))
- self.connect(self.ui.actionModules, SIGNAL("triggered()"), self.modulesConfig)
+ self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
self.connect(self.ui.tabWidget, SIGNAL('currentChanged(int)'), self.tabChanged)
- def modulesConfig(self):
+ def backendsConfig(self):
bckndcfg = BackendCfg(self.weboob, (ICapDating,), self)
bckndcfg.show()
diff --git a/weboob/applications/qhavesex/qhavesex.py b/weboob/applications/qhavesex/qhavesex.py
index c2c127a41515c3402bf3bb1f5f8c5de012c6e420..efcafbefe86edfa84da727d46f5829fdb2952a51 100644
--- a/weboob/applications/qhavesex/qhavesex.py
+++ b/weboob/applications/qhavesex/qhavesex.py
@@ -28,7 +28,7 @@ class QHaveSex(QtApplication):
STORAGE_FILENAME = 'dating.storage'
def main(self, argv):
- self.load_backends(ICapDating, storage=self.create_storage())
+ self.load_configured_backends(ICapDating, storage=self.create_storage())
self.main_window = MainWindow(self.config, self.weboob)
self.main_window.show()
diff --git a/weboob/applications/qhavesex/ui/main_window.ui b/weboob/applications/qhavesex/ui/main_window.ui
index 6a2b3e4774f600e3619d128279c331884e6c85fd..a04160d416d188b389b7ad38b85396c258395298 100644
--- a/weboob/applications/qhavesex/ui/main_window.ui
+++ b/weboob/applications/qhavesex/ui/main_window.ui
@@ -37,7 +37,7 @@
File
-
+
@@ -54,11 +54,11 @@
false
-
+
-
+
- Modules
+ Backends
diff --git a/weboob/applications/qvideoob/qvideoob.py b/weboob/applications/qvideoob/qvideoob.py
index 0fae8313900206f5c304b032184bb943849c3d6d..0362875941475775576dde5372cf4437866c7cf4 100644
--- a/weboob/applications/qvideoob/qvideoob.py
+++ b/weboob/applications/qvideoob/qvideoob.py
@@ -32,7 +32,7 @@ class QVideoob(QtApplication):
}
}
def main(self, argv):
- self.load_modules(ICapVideo)
+ self.load_backends(ICapVideo)
self.load_config()
self.main_window = MainWindow(self.config, self.weboob)
diff --git a/weboob/applications/qweboobcfg/qweboobcfg.py b/weboob/applications/qweboobcfg/qweboobcfg.py
index d269dbf1f55244349c181b1e8af723c3ce83b6ef..7c8f4925959c19608f5878c5ee8458e81c678133 100644
--- a/weboob/applications/qweboobcfg/qweboobcfg.py
+++ b/weboob/applications/qweboobcfg/qweboobcfg.py
@@ -27,7 +27,7 @@ class QWeboobCfg(QtApplication):
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
- self.load_backends()
+ self.load_configured_backends()
self.dlg = BackendCfg(self.weboob)
self.dlg.show()
diff --git a/weboob/applications/travel/application.py b/weboob/applications/travel/application.py
index 1172fb192fcc1e143495a9afa924f918b5dd209c..ca66ab3b0aed389c3945d78b9bd04e9cdee97efc 100644
--- a/weboob/applications/travel/application.py
+++ b/weboob/applications/travel/application.py
@@ -29,8 +29,7 @@ class Travel(ConsoleApplication):
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
- self.load_modules(ICapTravel)
-
+ self.load_backends(ICapTravel)
return self.process_command(*argv[1:])
@ConsoleApplication.command('Search stations')
diff --git a/weboob/applications/videoob/videoob.py b/weboob/applications/videoob/videoob.py
index 20cd1c3d2abdebf1e226a955e8e4879b275aa9bf..38aa231ffe266f10e62de2ae3b386411fd95c319 100644
--- a/weboob/applications/videoob/videoob.py
+++ b/weboob/applications/videoob/videoob.py
@@ -41,7 +41,7 @@ def main(self, argv):
def command_info(self, _id):
_id, backend_name = self.parse_id(_id)
names = (backend_name,) if backend_name is not None else None
- self.load_modules(ICapVideo, names=names)
+ self.load_backends(ICapVideo, names=names)
for backend, video in self.weboob.do('get_video', _id):
if video is None:
continue
@@ -49,7 +49,7 @@ def command_info(self, _id):
@ConsoleApplication.command('Search for videos')
def command_search(self, pattern=None):
- self.load_modules(ICapVideo)
+ self.load_backends(ICapVideo)
self.set_formatter_header(u'Search pattern: %s' % pattern if pattern else u'Last videos')
for backend, video in self.do('iter_search_results', pattern=pattern, nsfw=self.options.nsfw):
self.format(video, backend.name)
diff --git a/weboob/applications/videoob_web/videoob_web.py b/weboob/applications/videoob_web/videoob_web.py
index d40a5aee60853454c2b24f90133308f433a6b338..6466955c26f047a21b504e78881a69b3d270f6c2 100644
--- a/weboob/applications/videoob_web/videoob_web.py
+++ b/weboob/applications/videoob_web/videoob_web.py
@@ -72,7 +72,7 @@ def make_app(self, req):
def main(self, argv):
self.load_config()
- self.weboob.load_modules(ICapVideo)
+ self.weboob.load_backends(ICapVideo)
print 'Web server created. Listening on http://%s:%s' % (
self.config.get('host'), int(self.config.get('port')))
srv = make_server(self.config.get('host'), int(self.config.get('port')), self.make_app)
diff --git a/weboob/applications/weboobcfg/weboobcfg.py b/weboob/applications/weboobcfg/weboobcfg.py
index f49cef1a713ffaa2c87a9788bb3fa9b5e649ea74..117c317dc0da219f9c918b29836ffa7522d54796 100644
--- a/weboob/applications/weboobcfg/weboobcfg.py
+++ b/weboob/applications/weboobcfg/weboobcfg.py
@@ -44,65 +44,10 @@ def caps_included(self, modcaps, caps):
return False
return True
- @ConsoleApplication.command('List backends')
- def command_backends(self, *caps):
- self.set_default_formatter('table')
- self.weboob.modules_loader.load()
- for name, backend in self.weboob.modules_loader.modules.iteritems():
- if caps and not self.caps_included(backend.iter_caps(), caps):
- continue
- row = OrderedDict([('Name', name),
- ('Capabilities', ', '.join(cap.__name__ for cap in backend.iter_caps())),
- ('Description', backend.get_description()),
- ])
- self.format(row)
-
- @ConsoleApplication.command('List applications')
- def command_applications(self, *caps):
- applications = set()
- import weboob.applications
- for path in weboob.applications.__path__:
- regexp = re.compile('^%s/([\w\d_]+)$' % path)
- for root, dirs, files in os.walk(path):
- m = regexp.match(root)
- if m and '__init__.py' in files:
- applications.add(m.group(1))
- print ' '.join(sorted(applications)).encode('utf-8')
-
- @ConsoleApplication.command('Display information about a backend')
- def command_info(self, name):
- try:
- backend = self.weboob.modules_loader.get_or_load_module(name)
- except KeyError:
- logging.error('No such backend: "%s"' % name)
- return 1
-
- print '.------------------------------------------------------------------------------.'
- print '| Backend %-68s |' % backend.get_name()
- print "+-----------------.------------------------------------------------------------'"
- print '| Version | %s' % backend.get_version()
- print '| Maintainer | %s' % backend.get_maintainer()
- print '| License | %s' % backend.get_license()
- print '| Description | %s' % backend.get_description()
- print '| Capabilities | %s' % ', '.join([cap.__name__ for cap in backend.iter_caps()])
- first = True
- for key, field in backend.get_config().iteritems():
- value = field.description
- if not field.default is None:
- value += ' (default: %s)' % field.default
- if first:
- print '| | '
- print '| Configuration | %s: %s' % (key, value)
- first = False
- else:
- print '| | %s: %s' % (key, value)
- print "'-----------------'"
-
-
@ConsoleApplication.command('Add a configured backend')
def command_add(self, name, *options):
- self.weboob.modules_loader.load()
- if name not in [module_name for module_name, module in self.weboob.modules_loader.modules.iteritems()]:
+ self.weboob.backends_loader.load_all()
+ if name not in [name for name, backend in self.weboob.backends_loader.loaded.iteritems()]:
logging.error(u'Backend "%s" does not exist.' % name)
return 1
@@ -116,9 +61,9 @@ def command_add(self, name, *options):
return 1
params[key] = value
# ask for params non-specified on command-line arguments
- module = self.weboob.modules_loader.get_or_load_module(name)
+ backend = self.weboob.backends_loader.get_or_load_backend(name)
asked_config = False
- for key, value in module.get_config().iteritems():
+ for key, value in backend.config.iteritems():
if not asked_config:
asked_config = True
print u'Configuration of backend'
@@ -155,16 +100,74 @@ def command_add(self, name, *options):
except ConfigParser.DuplicateSectionError:
print u'Instance "%s" already exists for backend "%s".' % (new_name, name)
- @ConsoleApplication.command('List configured backends')
+ @ConsoleApplication.command('Show applications')
+ def command_applications(self, *caps):
+ applications = set()
+ import weboob.applications
+ for path in weboob.applications.__path__:
+ regexp = re.compile('^%s/([\w\d_]+)$' % path)
+ for root, dirs, files in os.walk(path):
+ m = regexp.match(root)
+ if m and '__init__.py' in files:
+ applications.add(m.group(1))
+ print ' '.join(sorted(applications)).encode('utf-8')
+
+ @ConsoleApplication.command('Show available backends')
+ def command_backends(self, *caps):
+ self.set_default_formatter('table')
+ self.weboob.backends_loader.load_all()
+ for name, backend in sorted(self.weboob.backends_loader.loaded.iteritems()):
+ if caps and not self.caps_included(backend.iter_caps(), caps):
+ continue
+ row = OrderedDict([('Name', name),
+ ('Capabilities', ', '.join(cap.__name__ for cap in backend.iter_caps())),
+ ('Description', backend.description),
+ ])
+ self.format(row)
+
+ @ConsoleApplication.command('Show configured backends')
def command_configured(self):
self.set_default_formatter('table')
- for instance_name, name, params in self.weboob.backends_config.iter_backends():
+ for instance_name, name, params in sorted(self.weboob.backends_config.iter_backends()):
row = OrderedDict([('Instance name', instance_name),
('Backend name', name),
('Configuration', ', '.join('%s=%s' % (key, value) for key, value in params.iteritems())),
])
self.format(row)
+ @ConsoleApplication.command('Edit configuration file')
+ def command_edit(self):
+ subprocess.call([os.environ.get('EDITOR', 'vi'), self.weboob.backends_config.confpath])
+
+ @ConsoleApplication.command('Display information about a backend')
+ def command_info(self, name):
+ try:
+ backend = self.weboob.backends_loader.get_or_load_backend(name)
+ except KeyError:
+ logging.error('No such backend: "%s"' % name)
+ return 1
+
+ print '.------------------------------------------------------------------------------.'
+ print '| Backend %-68s |' % backend.name
+ print "+-----------------.------------------------------------------------------------'"
+ print '| Version | %s' % backend.version
+ print '| Maintainer | %s' % backend.maintainer
+ print '| License | %s' % backend.license
+ print '| Description | %s' % backend.description
+ print '| Capabilities | %s' % ', '.join([cap.__name__ for cap in backend.iter_caps()])
+ first = True
+ for key, field in backend.config.iteritems():
+ value = field.description
+ if not field.default is None:
+ value += ' (default: %s)' % field.default
+ if first:
+ print '| | '
+ print '| Configuration | %s: %s' % (key, value)
+ first = False
+ else:
+ print '| | %s: %s' % (key, value)
+ print "'-----------------'"
+
@ConsoleApplication.command('Remove a configured backend')
def command_remove(self, instance_name):
try:
@@ -172,7 +175,3 @@ def command_remove(self, instance_name):
except ConfigParser.NoSectionError:
logging.error('Backend instance "%s" does not exist' % instance_name)
return 1
-
- @ConsoleApplication.command('Edit configuration file')
- def command_edit(self):
- subprocess.call([os.environ.get('EDITOR', 'vi'), self.weboob.backends_config.confpath])
diff --git a/weboob/applications/weboobdebug/weboobdebug.py b/weboob/applications/weboobdebug/weboobdebug.py
index dd46d616e881a1006a8b5388e244faa5d19d5de2..45ff70776fcf03881bfc55963f9ed0885b7b9a06 100644
--- a/weboob/applications/weboobdebug/weboobdebug.py
+++ b/weboob/applications/weboobdebug/weboobdebug.py
@@ -32,14 +32,14 @@ def main(self, argv):
@ConsoleApplication.command('Debug backend')
def command_shell(self, backend_name):
try:
- backend = self.weboob.load_modules(names=[backend_name])[backend_name]
+ backend = self.weboob.load_backends(names=[backend_name])[backend_name]
except KeyError:
logging.error(u'Unable to load backend "%s"' % backend_name)
return 1
browser = backend.browser
from IPython.Shell import IPShellEmbed
shell = IPShellEmbed(argv=[])
- locs = dict(backend=backend, browser=browser, frontend=self, weboob=self.weboob)
+ locs = dict(backend=backend, browser=browser, application=self, weboob=self.weboob)
banner = 'Weboob debug shell\nBackend "%s" loaded.\nAvailable variables: %s' % (backend_name, locs)
shell.set_banner(shell.IP.BANNER + '\n\n' + banner)
shell(local_ns=locs, global_ns={})
diff --git a/weboob/applications/weboobtests/weboobtests.py b/weboob/applications/weboobtests/weboobtests.py
index 9a065ad8ea7da4ffaee99265c53249916284a86f..5e1af689b5601541fac0f2028f4651f246e0b040 100644
--- a/weboob/applications/weboobtests/weboobtests.py
+++ b/weboob/applications/weboobtests/weboobtests.py
@@ -15,6 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
from nose import run
from weboob.tools.application.console import ConsoleApplication
@@ -32,13 +33,13 @@ def main(self, argv):
@ConsoleApplication.command('Run tests')
def command_run(self):
- self.load_modules()
self.load_backends()
+ self.load_configured_backends()
suite = []
for backend in self.weboob.iter_backends():
- t = backend.get_test()
- if t:
- suite.append(t)
+ test = backend.get_test()
+ if test:
+ suite.append(test)
return run(suite=suite)
diff --git a/weboob/applications/weboorrents/weboorrents.py b/weboob/applications/weboorrents/weboorrents.py
index 25f719c2a0116a7b1a3e1068d587e10a1551779d..f3c70e3826aa2fd92a11a0c4cef12ddcfce53afc 100644
--- a/weboob/applications/weboorrents/weboorrents.py
+++ b/weboob/applications/weboorrents/weboorrents.py
@@ -33,7 +33,7 @@ class Weboorrents(ConsoleApplication):
CONFIG = {}
def main(self, argv):
- self.load_backends(ICapTorrent)
+ self.load_configured_backends(ICapTorrent)
return self.process_command(*argv[1:])
@ConsoleApplication.command('Get information about a torrent')
diff --git a/weboob/applications/wetboobs/wetboobs.py b/weboob/applications/wetboobs/wetboobs.py
index 93b4ae31e2c7472d20fa5ec2da16d9a9e2f1ff85..4dc8887b3ca64103b9c00fb725463f523bc879db 100644
--- a/weboob/applications/wetboobs/wetboobs.py
+++ b/weboob/applications/wetboobs/wetboobs.py
@@ -32,7 +32,7 @@ class WetBoobs(ConsoleApplication):
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
- self.load_modules(ICapWeather)
+ self.load_backends(ICapWeather)
return self.process_command(*argv[1:])
diff --git a/weboob/core/modules.py b/weboob/core/backends.py
similarity index 69%
rename from weboob/core/modules.py
rename to weboob/core/backends.py
index ac429352bd15d2616c0136d5159aed1f19b511df..30831f108e1a274a9e6dfb941b900d2726b6b342 100644
--- a/weboob/core/modules.py
+++ b/weboob/core/backends.py
@@ -26,45 +26,50 @@
import stat
import weboob.backends
-from weboob.core.backend import BaseBackend
from weboob.capabilities.cap import ICap
+from weboob.tools.backend import BaseBackend
-__all__ = ['Module']
+__all__ = ['Backend', 'BackendsConfig', 'BackendsLoader']
-class Module(object):
- def __init__(self, name, module):
- self.name = name
- self.module = module
+class Backend(object):
+ def __init__(self, package):
+ self.package = package
self.klass = None
- for attrname in dir(self.module):
- attr = getattr(self.module, attrname)
+ for attrname in dir(self.package):
+ attr = getattr(self.package, attrname)
if isinstance(attr, type) and issubclass(attr, BaseBackend) and attr != BaseBackend:
self.klass = attr
-
if not self.klass:
- raise ImportError("This is not a backend module (no BaseBackend class found)")
+ raise ImportError('%s is not a backend (no BaseBackend class found)' % package)
- def get_name(self):
+ @property
+ def name(self):
return self.klass.NAME
- def get_maintainer(self):
+ @property
+ def maintainer(self):
return '%s <%s>' % (self.klass.MAINTAINER, self.klass.EMAIL)
- def get_version(self):
+ @property
+ def version(self):
return self.klass.VERSION
- def get_description(self):
+ @property
+ def description(self):
return self.klass.DESCRIPTION
- def get_license(self):
+ @property
+ def license(self):
return self.klass.LICENSE
- def get_config(self):
+ @property
+ def config(self):
return self.klass.CONFIG
- def get_icon_path(self):
+ @property
+ def icon_path(self):
return self.klass.ICON
def iter_caps(self):
@@ -78,9 +83,11 @@ def has_caps(self, *caps):
return True
return False
- def create_backend(self, weboob, name, config, storage):
- debug('Created backend "%s"' % name)
- return self.klass(weboob, name, config, storage)
+ def create_instance(self, weboob, name, config, storage):
+ backend_instance = self.klass(weboob, name, config, storage)
+ debug('Created backend instance "%s"' % name)
+ return backend_instance
+
class BackendsConfig(object):
class WrongPermissions(Exception):
@@ -128,7 +135,7 @@ def get_backend(self, name):
config = SafeConfigParser()
config.read(self.confpath)
if not config.has_section(name):
- raise KeyError(u'Backend "%s" not found' % name)
+ raise KeyError(u'Backend instance "%s" not found' % name)
items = dict(config.items(name, raw=True))
try:
@@ -141,19 +148,20 @@ def remove_backend(self, name):
config = SafeConfigParser()
config.read(self.confpath)
config.remove_section(name)
- with open(self.confpath, 'wb') as f:
+ with open(self.confpath, 'w') as f:
config.write(f)
-class ModulesLoader(object):
+
+class BackendsLoader(object):
def __init__(self):
- self.modules = {}
+ self.loaded = {}
- def get_or_load_module(self, name):
- if name not in self.modules:
- self.load_module('weboob.backends.%s' % name)
- return self.modules[name]
+ def get_or_load_backend(self, name):
+ if name not in self.loaded:
+ self.load_backend(name)
+ return self.loaded[name]
- def iter_existing_module_names(self):
+ def iter_existing_backend_names(self):
for path in weboob.backends.__path__:
regexp = re.compile('^%s/([\w\d_]+)$' % path)
for root, dirs, files in os.walk(path):
@@ -161,23 +169,24 @@ def iter_existing_module_names(self):
if m and '__init__.py' in files:
yield m.group(1)
- def load(self):
- for existing_module_name in self.iter_existing_module_names():
- self.load_module('weboob.backends.%s' % existing_module_name)
+ def load_all(self):
+ for existing_backend_name in self.iter_existing_backend_names():
+ self.load_backend(existing_backend_name)
- def load_module(self, name):
+ def load_backend(self, name):
try:
- module = Module(name, __import__(name, fromlist=[str(name)]))
+ package_name = 'weboob.backends.%s' % name
+ backend = Backend(__import__(package_name, fromlist=[str(package_name)]))
except ImportError, e:
- msg = 'Unable to load module "%s": %s' % (name, e)
+ msg = u'Unable to load backend "%s": %s' % (name, e)
if logging.root.level == logging.DEBUG:
exception(msg)
return
else:
error(msg)
return
- if module.get_name() in self.modules:
- warning('Module "%s" is already loaded (%s)' % (self.modules[module.get_name()].module, name))
+ if backend.name in self.loaded:
+ debug('Backend "%s" is already loaded from %s' % (name, backend.package.__path__[0]))
return
- self.modules[module.get_name()] = module
- debug('Loaded module "%s" from %s' % (name, module.module.__path__))
+ self.loaded[backend.name] = backend
+ debug('Loaded backend "%s" from %s' % (name, backend.package.__path__[0]))
diff --git a/weboob/core/ouiboube.py b/weboob/core/ouiboube.py
index febdeffec903022993d6edac25f8d4a1a435395b..f1e2b159e4d9f5d7ee877d037b0f64563dba607d 100644
--- a/weboob/core/ouiboube.py
+++ b/weboob/core/ouiboube.py
@@ -23,9 +23,9 @@
import sys
from weboob.core.bcall import BackendsCall
-from weboob.core.modules import ModulesLoader, BackendsConfig
-from weboob.core.backend import BaseBackend
+from weboob.core.backends import BackendsConfig, BackendsLoader
from weboob.core.scheduler import Scheduler
+from weboob.tools.backend import BaseBackend
if sys.version_info[:2] <= (2, 5):
import weboob.tools.property
@@ -40,7 +40,7 @@ class Weboob(object):
def __init__(self, workdir=WORKDIR, backends_filename=None, scheduler=None):
self.workdir = workdir
- self.backends = {}
+ self.backend_instances = {}
# Scheduler
if scheduler is None:
@@ -53,10 +53,10 @@ def __init__(self, workdir=WORKDIR, backends_filename=None, scheduler=None):
elif not os.path.isdir(self.workdir):
warning('"%s" is not a directory' % self.workdir)
- # Modules loader
- self.modules_loader = ModulesLoader()
+ # Backends loader
+ self.backends_loader = BackendsLoader()
- # Backends config
+ # Backend instances config
if not backends_filename:
backends_filename = os.path.join(self.workdir, self.BACKENDS_FILENAME)
elif not backends_filename.startswith('/'):
@@ -64,41 +64,26 @@ def __init__(self, workdir=WORKDIR, backends_filename=None, scheduler=None):
self.backends_config = BackendsConfig(backends_filename)
def load_backends(self, caps=None, names=None, storage=None):
- loaded_backends = {}
- for name, _type, params in self.backends_config.iter_backends():
- try:
- module = self.modules_loader.get_or_load_module(_type)
- except KeyError:
- warning(u'Unable to find module "%s" for backend "%s"' % (_type, name))
+ loaded = {}
+ self.backends_loader.load_all()
+ for backend_name, backend in self.backends_loader.loaded.iteritems():
+ if caps is not None and not backend.has_caps(caps) or \
+ names is not None and backend_name not in names:
continue
-
- # Check conditions
- if caps is not None and not module.has_caps(caps) or \
- names is not None and name not in names:
- continue
-
- try:
- self.backends[name] = module.create_backend(self, name, params, storage)
- loaded_backends[name] = self.backends[name]
- except Exception, e:
- warning(u'Unable to load "%s" backend: %s. filename=%s' % (name, e, self.backends_config.confpath))
-
- return loaded_backends
-
- def load_modules(self, caps=None, names=None, storage=None):
- loaded_backends = {}
- self.modules_loader.load()
- for name, module in self.modules_loader.modules.iteritems():
- if caps is not None and not module.has_caps(caps) or \
- names is not None and name not in names:
+ backend_instance = backend.create_instance(self, backend_name, {}, storage)
+ self.backend_instances[backend_name] = loaded[backend_name] = backend_instance
+ return loaded
+
+ def load_configured_backends(self, caps=None, names=None, storage=None):
+ loaded = {}
+ for instance_name, backend_name, params in self.backends_config.iter_backends():
+ backend = self.backends_loader.get_or_load_backend(backend_name)
+ if caps is not None and not backend.has_caps(caps) or \
+ names is not None and instance_name not in names:
continue
- try:
- name = module.get_name()
- self.backends[name] = module.create_backend(self, name, {}, storage)
- loaded_backends[name] = self.backends[name]
- except Exception, e:
- warning(u'Unable to load "%s" module as backend with no config: %s' % (name, e))
- return loaded_backends
+ backend_instance = backend.create_instance(self, instance_name, params, storage)
+ self.backend_instances[instance_name] = loaded[instance_name] = backend_instance
+ return loaded
def iter_backends(self, caps=None):
"""
@@ -109,7 +94,7 @@ def iter_backends(self, caps=None):
@param caps Optional list of capabilities to select backends
@return iterator on selected backends.
"""
- for name, backend in sorted(self.backends.iteritems()):
+ for name, backend in sorted(self.backend_instances.iteritems()):
if caps is None or backend.has_caps(caps):
with backend:
yield backend
@@ -134,7 +119,7 @@ def do(self, function, *args, **kwargs):
def do_caps(self, caps, function, *args, **kwargs):
"""
- Do calls on loaded modules with the specified capabilities, in
+ Do calls on loaded backends with the specified capabilities, in
separated threads.
See also documentation of the 'do' method.
@@ -156,14 +141,14 @@ def do_backends(self, backends, function, *args, **kwargs):
elif isinstance(backends, (list,tuple)):
old_backends = backends
backends = []
- for b in old_backends:
- if isinstance(b, (str,unicode)):
+ for backend in old_backends:
+ if isinstance(backend, (str,unicode)):
try:
- backends.append(self.backends[self.backends.index(b)])
+ backends.append(self.backends[self.backends.index(backend)])
except ValueError:
pass
else:
- backends.append(b)
+ backends.append(backend)
return BackendsCall(backends, function, *args, **kwargs)
def schedule(self, interval, function, *args):
diff --git a/weboob/tools/application/base.py b/weboob/tools/application/base.py
index e3de6d4a23c039d0fa5746d70c3a8a06a4754dcf..5260b3b7aaa97c09138de3f27b409ad304281422 100644
--- a/weboob/tools/application/base.py
+++ b/weboob/tools/application/base.py
@@ -32,28 +32,28 @@ class BackendNotFound(Exception):
pass
-class FrontendStorage(object):
+class ApplicationStorage(object):
def __init__(self, name, storage):
self.name = name
self.storage = storage
def set(self, *args):
if self.storage:
- return self.storage.set('frontends', self.name, *args)
+ return self.storage.set('applications', self.name, *args)
def get(self, *args, **kwargs):
if self.storage:
- return self.storage.get('frontends', self.name, *args, **kwargs)
+ return self.storage.get('applications', self.name, *args, **kwargs)
else:
return kwargs.get('default', None)
def load(self, default):
if self.storage:
- return self.storage.load('frontends', self.name, default)
+ return self.storage.load('applications', self.name, default)
def save(self):
if self.storage:
- return self.storage.save('frontends', self.name)
+ return self.storage.save('applications', self.name)
class BaseApplication(object):
# Application name
@@ -107,7 +107,7 @@ def create_storage(self, path=None, klass=None):
path = os.path.join(self.CONFDIR, path)
storage = klass(path)
- self.storage = FrontendStorage(self.APPNAME, storage)
+ self.storage = ApplicationStorage(self.APPNAME, storage)
self.storage.load(self.STORAGE)
return storage
@@ -138,18 +138,18 @@ def main(self, argv):
def load_backends(self, caps=None, names=None, *args, **kwargs):
if names is None:
names = self.requested_backends
- loaded_backends = self.weboob.load_backends(caps, names, *args, **kwargs)
- if not loaded_backends:
+ loaded = self.weboob.load_backends(caps, names, *args, **kwargs)
+ if not loaded:
logging.warning(u'No backend loaded')
- return loaded_backends
+ return loaded
- def load_modules(self, caps=None, names=None, *args, **kwargs):
+ def load_configured_backends(self, caps=None, names=None, *args, **kwargs):
if names is None:
names = self.requested_backends
- loaded_modules = self.weboob.load_modules(caps, names, *args, **kwargs)
- if not loaded_modules:
- logging.warning(u'No module loaded')
- return loaded_modules
+ loaded = self.weboob.load_configured_backends(caps, names, *args, **kwargs)
+ if not loaded:
+ logging.warning(u'No configured backend loaded')
+ return loaded
def _get_completions(self):
"""
@@ -201,9 +201,9 @@ def run(klass, args=None):
logging.basicConfig(stream=sys.stdout, level=level, format=log_format)
app.requested_backends = app.options.backends.split(',') if app.options.backends else None
if app.requested_backends:
- existing_module_names = list(app.weboob.modules_loader.iter_existing_module_names())
+ existing_backend_names = list(app.weboob.backends_loader.iter_existing_backend_names())
for requested_backend in app.requested_backends:
- if requested_backend not in existing_module_names:
+ if requested_backend not in existing_backend_names:
raise BackendNotFound(u'Unknown backend: "%s"' % requested_backend)
app._handle_app_options()
diff --git a/weboob/tools/application/console.py b/weboob/tools/application/console.py
index 962acce27c42ba5eef652577ecc872570df1de5a..76eb4c0926b04adb54d290d18ac69f2d4995839f 100644
--- a/weboob/tools/application/console.py
+++ b/weboob/tools/application/console.py
@@ -24,7 +24,7 @@
import sys
from weboob.core import CallErrors
-from weboob.core.modules import BackendsConfig
+from weboob.core.backends import BackendsConfig
from .base import BackendNotFound, BaseApplication
from .formatters.load import formatters, load_formatter
diff --git a/weboob/tools/application/qt/backendcfg.py b/weboob/tools/application/qt/backendcfg.py
index d8af23baeb726500ef3138f21c60753c80b3e340..62189c5aed982767216cfda782e0aed5180e73d9 100644
--- a/weboob/tools/application/qt/backendcfg.py
+++ b/weboob/tools/application/qt/backendcfg.py
@@ -35,50 +35,50 @@ def __init__(self, weboob, caps=None, parent=None):
self.caps = caps
self.config_widgets = {}
- self.weboob.modules_loader.load()
+ self.weboob.backends_loader.load_all()
- self.ui.backendsList.header().setResizeMode(QHeaderView.ResizeToContents)
+ self.ui.configuredBackendsList.header().setResizeMode(QHeaderView.ResizeToContents)
self.ui.configFrame.hide()
- for name, module in self.weboob.modules_loader.modules.iteritems():
- if not self.caps or module.has_caps(*self.caps):
+ for name, backend in self.weboob.backends_loader.loaded.iteritems():
+ if not self.caps or backend.has_caps(*self.caps):
item = QListWidgetItem(name.capitalize())
- if module.get_icon_path():
- img = QImage(module.get_icon_path())
+ if backend.icon_path:
+ img = QImage(backend.icon_path)
item.setIcon(QIcon(QPixmap.fromImage(img)))
- self.ui.modulesList.addItem(item)
+ self.ui.backendsList.addItem(item)
- self.loadBackendsList()
+ self.loadConfiguredBackendsList()
- self.connect(self.ui.backendsList, SIGNAL('itemClicked(QTreeWidgetItem *, int)'), self.backendClicked)
- self.connect(self.ui.modulesList, SIGNAL('itemSelectionChanged()'), self.modulesSelectionChanged)
+ self.connect(self.ui.configuredBackendsList, SIGNAL('itemClicked(QTreeWidgetItem *, int)'), self.configuredBackendClicked)
+ self.connect(self.ui.backendsList, SIGNAL('itemSelectionChanged()'), self.backendSelectionChanged)
self.connect(self.ui.proxyBox, SIGNAL('toggled(bool)'), self.proxyEditEnabled)
self.connect(self.ui.addButton, SIGNAL('clicked()'), self.addEvent)
self.connect(self.ui.removeButton, SIGNAL('clicked()'), self.removeEvent)
self.connect(self.ui.configButtonBox, SIGNAL('accepted()'), self.acceptBackend)
self.connect(self.ui.configButtonBox, SIGNAL('rejected()'), self.rejectBackend)
- def loadBackendsList(self):
- self.ui.backendsList.clear()
+ def loadConfiguredBackendsList(self):
+ self.ui.configuredBackendsList.clear()
for instance_name, name, params in self.weboob.backends_config.iter_backends():
- module = self.weboob.modules_loader.modules[name]
- if self.caps and not module.has_caps(*self.caps):
+ backend = self.weboob.backends_loader.loaded[name]
+ if self.caps and not backend.has_caps(*self.caps):
continue
item = QTreeWidgetItem(None, [instance_name, name])
- if module.get_icon_path():
- img = QImage(module.get_icon_path())
+ if backend.icon_path:
+ img = QImage(backend.icon_path)
item.setIcon(0, QIcon(QPixmap.fromImage(img)))
- self.ui.backendsList.addTopLevelItem(item)
+ self.ui.configuredBackendsList.addTopLevelItem(item)
def closeEvent(self, event):
event.accept()
- def backendClicked(self, item, col):
+ def configuredBackendClicked(self, item, col):
bname = unicode(item.text(0))
self.editBackend(bname)
@@ -87,7 +87,7 @@ def addEvent(self):
self.editBackend()
def removeEvent(self):
- item = self.ui.backendsList.currentItem()
+ item = self.ui.configuredBackendsList.currentItem()
if not item:
return
@@ -100,7 +100,7 @@ def removeEvent(self):
return
self.weboob.backends_config.remove_backend(bname)
- self.loadBackendsList()
+ self.loadConfiguredBackendsList()
def editBackend(self, bname=None):
self.ui.configFrame.show()
@@ -108,12 +108,12 @@ def editBackend(self, bname=None):
if bname is not None:
mname, params = self.weboob.backends_config.get_backend(bname)
- items = self.ui.modulesList.findItems(mname, Qt.MatchFixedString)
+ items = self.ui.backendsList.findItems(mname, Qt.MatchFixedString)
if not items:
- print 'Module not found'
+ print 'Backend not found'
else:
- self.ui.modulesList.setCurrentItem(items[0])
- self.ui.modulesList.setEnabled(False)
+ self.ui.backendsList.setCurrentItem(items[0])
+ self.ui.backendsList.setEnabled(False)
self.ui.nameEdit.setText(bname)
self.ui.nameEdit.setEnabled(False)
@@ -137,19 +137,19 @@ def editBackend(self, bname=None):
self.ui.nameEdit.setEnabled(True)
self.ui.proxyBox.setChecked(False)
self.ui.proxyEdit.clear()
- self.ui.modulesList.setEnabled(True)
- self.ui.modulesList.setCurrentRow(-1)
+ self.ui.backendsList.setEnabled(True)
+ self.ui.backendsList.setCurrentRow(-1)
def acceptBackend(self):
bname = unicode(self.ui.nameEdit.text())
- selection = self.ui.modulesList.selectedItems()
+ selection = self.ui.backendsList.selectedItems()
if not selection:
- QMessageBox.critical(self, self.tr('Unable to add a backend'),
- self.tr('Please select a module'))
+ QMessageBox.critical(self, self.tr('Unable to add a configured backend'),
+ self.tr('Please select a backend'))
return
- module = self.weboob.modules_loader.modules[unicode(selection[0].text()).lower()]
+ backend = self.weboob.backends_loader.loaded[unicode(selection[0].text()).lower()]
params = {}
missing = []
@@ -162,7 +162,7 @@ def acceptBackend(self):
if not params['_proxy']:
missing.append(self.tr('Proxy'))
- for key, field in module.get_config().iteritems():
+ for key, field in backend.config.iteritems():
label, value = self.config_widgets[key]
if isinstance(value, QLineEdit):
@@ -189,49 +189,49 @@ def acceptBackend(self):
unicode(self.tr('Please set a value in this fields:\n%s')) % ('\n'.join(['- %s' % s for s in missing])))
return
- self.weboob.backends_config.add_backend(bname, module.get_name(), params, edit=not self.ui.nameEdit.isEnabled())
+ self.weboob.backends_config.add_backend(bname, backend.name, params, edit=not self.ui.nameEdit.isEnabled())
self.ui.configFrame.hide()
- self.loadBackendsList()
+ self.loadConfiguredBackendsList()
def rejectBackend(self):
self.ui.configFrame.hide()
- def modulesSelectionChanged(self):
+ def backendSelectionChanged(self):
for key, (label, value) in self.config_widgets.iteritems():
label.hide()
value.hide()
self.ui.configLayout.removeWidget(label)
self.ui.configLayout.removeWidget(value)
self.config_widgets.clear()
- self.ui.moduleInfo.clear()
+ self.ui.backendInfo.clear()
- selection = self.ui.modulesList.selectedItems()
+ selection = self.ui.backendsList.selectedItems()
if not selection:
return
- module = self.weboob.modules_loader.modules[unicode(selection[0].text()).lower()]
+ backend = self.weboob.backends_loader.loaded[unicode(selection[0].text()).lower()]
- if module.get_icon_path():
- img = QImage(module.get_icon_path())
- self.ui.moduleInfo.document().addResource(QTextDocument.ImageResource, QUrl('mydata://logo.png'), QVariant(img))
+ if backend.icon_path:
+ img = QImage(backend.icon_path)
+ self.ui.backendInfo.document().addResource(QTextDocument.ImageResource, QUrl('mydata://logo.png'), QVariant(img))
- self.ui.moduleInfo.setText(unicode(self.tr(
- '%s Module %s
'
+ self.ui.backendInfo.setText(unicode(self.tr(
+ '%s Backend %s
'
'Version: %s
'
'Maintainer: %s
'
'License: %s
'
'Description: %s
'
'Capabilities: %s
'))
- % ('' if module.get_icon_path() else '',
- module.get_name().capitalize(),
- module.get_version(),
- module.get_maintainer().replace('&', '&').replace('<', '<').replace('>', '>'),
- module.get_license(),
- module.get_description(),
- ', '.join([cap.__name__ for cap in module.iter_caps()])))
-
- for key, field in module.get_config().iteritems():
+ % ('' if backend.icon_path else '',
+ backend.name.capitalize(),
+ backend.version,
+ backend.maintainer.replace('&', '&').replace('<', '<').replace('>', '>'),
+ backend.license,
+ backend.description,
+ ', '.join([cap.__name__ for cap in backend.iter_caps()])))
+
+ for key, field in backend.config.iteritems():
label = QLabel(u'%s:' % field.description)
if isinstance(field.default, bool):
value = QCheckBox()
diff --git a/weboob/tools/application/qt/backendcfg.ui b/weboob/tools/application/qt/backendcfg.ui
index 2cf3d7e5f5fb66ca1f150809b21f98623391e21e..e6597f850fe83adf51f898bad8e7a0a89077e14a 100644
--- a/weboob/tools/application/qt/backendcfg.ui
+++ b/weboob/tools/application/qt/backendcfg.ui
@@ -6,8 +6,8 @@
0
0
- 626
- 614
+ 645
+ 652
@@ -22,7 +22,7 @@
-
-
+
QAbstractItemView::NoEditTriggers
@@ -72,7 +72,7 @@
- Module
+ Backend
@@ -125,99 +125,107 @@
QFrame::Raised
-
+
-
-
-
- Qt::Horizontal
+
+
-
+
+
+ Available backends
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 32
+ 32
+
+
+
+ 1
+
+
+ true
+
+
+
+
+
+ -
+
+
+
+ 1
+ 0
+
-
-
-
- 0
- 0
-
-
-
-
- 32
- 32
-
-
-
- 1
-
-
- true
-
-
-
-
-
- 1
- 0
-
-
-
- QFrame::NoFrame
-
-
- QFrame::Plain
-
-
-
-
-
-
-
-
-
- Name:
-
-
-
- -
-
-
- -
-
-
- Proxy:
-
-
-
- -
-
-
- false
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- true
-
-
-
-
-
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Name:
+
+
+
+ -
+
+
+ -
+
+
+ Proxy:
+
+
+
+ -
+
+
+ false
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+