From 5c2ab81e167b8090c83ec834ff0d582abd0b3f30 Mon Sep 17 00:00:00 2001 From: Christophe Benz Date: Mon, 12 Jul 2010 03:07:10 +0200 Subject: [PATCH] change vocabulary s/module/backend s/backend/configured_backend s/frontend/application --- weboob/applications/boobank/boobank.py | 2 +- weboob/applications/chatoob/chatoob.py | 2 +- weboob/applications/havesex/havesex.py | 2 +- .../applications/masstransit/masstransit.py | 3 +- weboob/applications/monboob/monboob.py | 2 +- weboob/applications/qboobmsg/main_window.py | 4 +- weboob/applications/qboobmsg/qboobmsg.py | 2 +- .../applications/qboobmsg/ui/main_window.ui | 8 +- weboob/applications/qhavesex/main_window.py | 4 +- weboob/applications/qhavesex/qhavesex.py | 2 +- .../applications/qhavesex/ui/main_window.ui | 8 +- weboob/applications/qvideoob/qvideoob.py | 2 +- weboob/applications/qweboobcfg/qweboobcfg.py | 2 +- weboob/applications/travel/application.py | 3 +- weboob/applications/videoob/videoob.py | 4 +- .../applications/videoob_web/videoob_web.py | 2 +- weboob/applications/weboobcfg/weboobcfg.py | 129 ++++++------ .../applications/weboobdebug/weboobdebug.py | 4 +- .../applications/weboobtests/weboobtests.py | 9 +- .../applications/weboorrents/weboorrents.py | 2 +- weboob/applications/wetboobs/wetboobs.py | 2 +- weboob/core/{modules.py => backends.py} | 87 ++++---- weboob/core/ouiboube.py | 73 +++---- weboob/tools/application/base.py | 32 +-- weboob/tools/application/console.py | 2 +- weboob/tools/application/qt/backendcfg.py | 100 ++++----- weboob/tools/application/qt/backendcfg.ui | 198 +++++++++--------- 27 files changed, 345 insertions(+), 345 deletions(-) rename weboob/core/{modules.py => backends.py} (69%) diff --git a/weboob/applications/boobank/boobank.py b/weboob/applications/boobank/boobank.py index db36d232..47393baf 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 a110a12a..f3af8527 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 2a6dad15..4c510d70 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 bfd72b6e..05a5f34a 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 3876ec6f..4786f8c3 100644 --- a/weboob/applications/monboob/monboob.py +++ b/weboob/applications/monboob/monboob.py @@ -93,7 +93,7 @@ class Monboob(ConsoleApplication): 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 8b7d56af..9eeee2c4 100644 --- a/weboob/applications/qboobmsg/main_window.py +++ b/weboob/applications/qboobmsg/main_window.py @@ -36,10 +36,10 @@ class MainWindow(QtMainWindow): 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 732f29a1..0c0510e2 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 330e9460..f40742b6 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 276d6948..db595c93 100644 --- a/weboob/applications/qhavesex/main_window.py +++ b/weboob/applications/qhavesex/main_window.py @@ -44,10 +44,10 @@ class MainWindow(QtMainWindow): 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 c2c127a4..efcafbef 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 6a2b3e47..a04160d4 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 0fae8313..03628759 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 d269dbf1..7c8f4925 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 1172fb19..ca66ab3b 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 20cd1c3d..38aa231f 100644 --- a/weboob/applications/videoob/videoob.py +++ b/weboob/applications/videoob/videoob.py @@ -41,7 +41,7 @@ class Videoob(ConsoleApplication): 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 @@ class Videoob(ConsoleApplication): @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 d40a5aee..6466955c 100644 --- a/weboob/applications/videoob_web/videoob_web.py +++ b/weboob/applications/videoob_web/videoob_web.py @@ -72,7 +72,7 @@ class VideoobWeb(BaseApplication): 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 f49cef1a..117c317d 100644 --- a/weboob/applications/weboobcfg/weboobcfg.py +++ b/weboob/applications/weboobcfg/weboobcfg.py @@ -44,65 +44,10 @@ class WeboobCfg(ConsoleApplication): 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 @@ class WeboobCfg(ConsoleApplication): 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 @@ class WeboobCfg(ConsoleApplication): 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 @@ class WeboobCfg(ConsoleApplication): 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 dd46d616..45ff7077 100644 --- a/weboob/applications/weboobdebug/weboobdebug.py +++ b/weboob/applications/weboobdebug/weboobdebug.py @@ -32,14 +32,14 @@ class WeboobDebug(ConsoleApplication): @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 9a065ad8..5e1af689 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 @@ class WeboobTests(ConsoleApplication): @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 25f719c2..f3c70e38 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 93b4ae31..4dc8887b 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 ac429352..30831f10 100644 --- a/weboob/core/modules.py +++ b/weboob/core/backends.py @@ -26,45 +26,50 @@ import re 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 @@ class Module(object): 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 @@ class BackendsConfig(object): 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 @@ class BackendsConfig(object): 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 @@ class ModulesLoader(object): 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 febdeffe..f1e2b159 100644 --- a/weboob/core/ouiboube.py +++ b/weboob/core/ouiboube.py @@ -23,9 +23,9 @@ import os 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 @@ class Weboob(object): 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 @@ class Weboob(object): 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 + backend_instance = backend.create_instance(self, backend_name, {}, storage) + self.backend_instances[backend_name] = loaded[backend_name] = backend_instance + return loaded - # Check conditions - if caps is not None and not module.has_caps(caps) or \ - names is not None and name not in names: + 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: - 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: - 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 @@ class Weboob(object): @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 @@ class Weboob(object): 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 @@ class Weboob(object): 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 e3de6d4a..5260b3b7 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 @@ class BaseApplication(object): 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 @@ class BaseApplication(object): 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 @@ class BaseApplication(object): 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 962acce2..76eb4c09 100644 --- a/weboob/tools/application/console.py +++ b/weboob/tools/application/console.py @@ -24,7 +24,7 @@ import re 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 d8af23ba..62189c5a 100644 --- a/weboob/tools/application/qt/backendcfg.py +++ b/weboob/tools/application/qt/backendcfg.py @@ -35,50 +35,50 @@ class BackendCfg(QDialog): 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 @@ class BackendCfg(QDialog): self.editBackend() def removeEvent(self): - item = self.ui.backendsList.currentItem() + item = self.ui.configuredBackendsList.currentItem() if not item: return @@ -100,7 +100,7 @@ class BackendCfg(QDialog): 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 @@ class BackendCfg(QDialog): 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 @@ class BackendCfg(QDialog): 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 @@ class BackendCfg(QDialog): 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 @@ class BackendCfg(QDialog): 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()]))) + % ('' 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 module.get_config().iteritems(): + 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 2cf3d7e5..e6597f85 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 + + + +