def __init__(self, workdir=None, datadir=None, backends_filename=None, scheduler=None, storage=None): super(Weboob, self).__init__(modules_path=False, scheduler=scheduler, storage=storage) # Create WORKDIR if workdir is None: if 'WEBOOB_WORKDIR' in os.environ: workdir = os.environ['WEBOOB_WORKDIR'] else: workdir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')), 'weboob') self.workdir = os.path.realpath(workdir) self._create_dir(workdir) # Create DATADIR if datadir is None: if 'WEBOOB_DATADIR' in os.environ: datadir = os.environ['WEBOOB_DATADIR'] elif 'WEBOOB_WORKDIR' in os.environ: datadir = os.environ['WEBOOB_WORKDIR'] else: datadir = os.path.join(os.environ.get('XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share')), 'weboob') _datadir = os.path.realpath(datadir) self._create_dir(_datadir) # Modules management self.repositories = Repositories(workdir, _datadir, self.VERSION) self.modules_loader = RepositoryModulesLoader(self.repositories) # Backend instances config if not backends_filename: backends_filename = os.environ.get('WEBOOB_BACKENDS', os.path.join(self.workdir, self.BACKENDS_FILENAME)) elif not backends_filename.startswith('/'): backends_filename = os.path.join(self.workdir, backends_filename) self.backends_config = BackendsConfig(backends_filename)
class Weboob(WebNip): """ The main class of Weboob, used to manage backends, modules repositories and call methods on all loaded backends. :param workdir: optional parameter to set path of the working directory :type workdir: str :param datadir: optional parameter to set path of the data directory :type datadir: str :param backends_filename: name of the *backends* file, where configuration of backends is stored :type backends_filename: str :param storage: provide a storage where backends can save data :type storage: :class:`weboob.tools.storage.IStorage` """ BACKENDS_FILENAME = 'backends' def __init__(self, workdir=None, datadir=None, backends_filename=None, scheduler=None, storage=None): super(Weboob, self).__init__(modules_path=False, scheduler=scheduler, storage=storage) # Create WORKDIR if workdir is None: if 'WEBOOB_WORKDIR' in os.environ: workdir = os.environ['WEBOOB_WORKDIR'] else: workdir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')), 'weboob') self.workdir = os.path.realpath(workdir) self._create_dir(workdir) # Create DATADIR if datadir is None: if 'WEBOOB_DATADIR' in os.environ: datadir = os.environ['WEBOOB_DATADIR'] elif 'WEBOOB_WORKDIR' in os.environ: datadir = os.environ['WEBOOB_WORKDIR'] else: datadir = os.path.join(os.environ.get('XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share')), 'weboob') _datadir = os.path.realpath(datadir) self._create_dir(_datadir) # Modules management self.repositories = Repositories(workdir, _datadir, self.VERSION) self.modules_loader = RepositoryModulesLoader(self.repositories) # Backend instances config if not backends_filename: backends_filename = os.environ.get('WEBOOB_BACKENDS', os.path.join(self.workdir, self.BACKENDS_FILENAME)) elif not backends_filename.startswith('/'): backends_filename = os.path.join(self.workdir, backends_filename) self.backends_config = BackendsConfig(backends_filename) def _create_dir(self, name): if not os.path.exists(name): os.makedirs(name) elif not os.path.isdir(name): self.logger.error(u'"%s" is not a directory', name) def update(self, progress=PrintProgress()): """ Update modules from repositories. """ self.repositories.update(progress) modules_to_check = set([module_name for _, module_name, _ in self.backends_config.iter_backends()]) for module_name in modules_to_check: minfo = self.repositories.get_module_info(module_name) if minfo and not minfo.is_installed(): self.repositories.install(minfo, progress) def build_backend(self, module_name, params=None, storage=None, name=None, nofail=False): """ Create a single backend which is not listed in configuration. :param module_name: name of module :param params: parameters to give to backend :type params: :class:`dict` :param storage: storage to use :type storage: :class:`weboob.tools.storage.IStorage` :param name: name of backend :type name: :class:`basestring` :rtype: :class:`weboob.tools.backend.Module` :param nofail: if true, this call can't fail :type nofail: :class:`bool` """ minfo = self.repositories.get_module_info(module_name) if minfo is None: raise ModuleLoadError(module_name, 'Module does not exist.') if not minfo.is_installed(): self.repositories.install(minfo) return super(Weboob, self).build_backend(module_name, params, storage, name, nofail) def load_backends(self, caps=None, names=None, modules=None, exclude=None, storage=None, errors=None): """ Load backends listed in config file. :param caps: load backends which implement all of specified caps :type caps: tuple[:class:`weboob.capabilities.base.Capability`] :param names: load backends in list :type names: tuple[:class:`str`] :param modules: load backends which module is in list :type modules: tuple[:class:`str`] :param exclude: do not load backends in list :type exclude: tuple[:class:`str`] :param storage: use this storage if specified :type storage: :class:`weboob.tools.storage.IStorage` :param errors: if specified, store every errors in this list :type errors: list[:class:`LoadError`] :returns: loaded backends :rtype: dict[:class:`str`, :class:`weboob.tools.backend.Module`] """ loaded = {} if storage is None: storage = self.storage if not self.repositories.check_repositories(): self.logger.error(u'Repositories are not consistent with the sources.list') raise VersionsMismatchError(u'Versions mismatch, please run "weboob-config update"') for backend_name, module_name, params in self.backends_config.iter_backends(): if '_enabled' in params and not params['_enabled'].lower() in ('1', 'y', 'true', 'on', 'yes') or \ names is not None and backend_name not in names or \ modules is not None and module_name not in modules or \ exclude is not None and backend_name in exclude: continue minfo = self.repositories.get_module_info(module_name) if minfo is None: self.logger.warning(u'Backend "%s" is referenced in %s but was not found. ' u'Perhaps a missing repository or a removed module?', module_name, self.backends_config.confpath) continue if caps is not None and not minfo.has_caps(caps): continue if not minfo.is_installed(): self.repositories.install(minfo) module = None try: module = self.modules_loader.get_or_load_module(module_name) except ModuleLoadError as e: self.logger.error(u'Unable to load module "%s": %s', module_name, e) continue if backend_name in self.backend_instances: self.logger.warning(u'Oops, the backend "%s" is already loaded. Unload it before reloading...', backend_name) self.unload_backends(backend_name) try: backend_instance = module.create_instance(self, backend_name, params, storage) except Module.ConfigError as e: if errors is not None: errors.append(self.LoadError(backend_name, e)) else: self.backend_instances[backend_name] = loaded[backend_name] = backend_instance return loaded def load_or_install_module(self, module_name): """ Load a backend, and install it if not done before """ try: return self.modules_loader.get_or_load_module(module_name) except ModuleLoadError: self.repositories.install(module_name) return self.modules_loader.get_or_load_module(module_name)