import glob import logging import os from collections import namedtuple from copy import copy from pprint import pprint from types import SimpleNamespace from xdg import BaseDirectory from . import exceptions as error from .catalog import Catalog from .framework import DictItem, scoped_ident from .idents import Idents from .lib.utils import import_module, open_yaml from .meta import NAME, VERSION from .providers import Providers logger = logging.getLogger(__name__) IamException = error.IamException class App: name = NAME def __init__(self, ident="_", config_path=None): # Load application db = self.load_config_files(config_path=config_path) self.load_db(db) self.init_ident(ident) def init_ident(self, ident): "Init application with ident" self.ident_raw = ident # # Split ident from scope # scope = "" # if "/" in ident: # parts = ident.split("/", 2) # ident = parts[0] # scope = parts[1] view = scoped_ident(ident) # Save important vars self.ident_name = view.ident self.ident_scope = view.scope # Fetch ident config if ident == "_" or not ident: logger.debug("Enable default ident") self.ident = self.idents.items_class("default") else: self.ident = self.idents.get(self.ident_name) # Load user and catalog self.catalog = Catalog(self, self.ident) def load_config_files(self, config_path=None): "Fetch config from default place" config_candidates = [] # Load file or config if config_path is not None: path = config_path else: path = os.path.join(BaseDirectory.xdg_config_home, self.name) if os.path.isdir(path): files = glob.glob("*.yml", root_dir=path) for file_ in files: file_ = os.path.join(path, file_) payloads = open_yaml(file_) for payload in payloads: config_candidates.append( ( file_, payload, ) ) if len(config_candidates) == 0: _msg = f"Can't find any yaml configuration in: {path}" raise error.MissingConfigFiles(_msg) config = {} for cand in config_candidates: path, conf = cand config.update(conf) return config def load_db(self, db): "Load database" # Init Databases self.db = db self._load_plugins(db.get("plugins", [])) # Load providers providers_conf = {} providers_conf.update(self.plugin_providers) providers_conf.update(db.get("providers", {})) # pprint (providers_conf) self.providers = Providers("ConfigProviders", providers_conf) # Load idents idents_conf = { # "_": {}, } idents_conf.update(db.get("idents", {})) self.idents = Idents("ConfigIdents", idents_conf) def _load_plugins(self, plugins_refs): "Load plugins" plugins = {} for plugin_name in plugins_refs: if not ":" in plugin_name: plugin_name = plugin_name + ":all" load_one = False if not plugin_name.endswith(":all"): load_one = plugin_name.split(":", 2)[1] mod = None try: mod = import_module(plugin_name) except ModuleNotFoundError as err: msg = f"Impossible to load module: {plugin_name}" raise IamException(msg) print(err) continue if load_one: mod = {load_one: mod} plugins.update(mod) self.plugin_providers = plugins def user_dump(self, pattern=None): "Dump ident config" self.catalog.dump() def get_idents(self, extended=False): "Return list of identities" ret = list(self.idents.get_idents()) if extended: out = ["mrjk/backups", "mrjk/pictures"] ret.extend(out) return ret # def get_resource(self, name): # "Query and resolve a resource" # return self.catalog.get_resource(name) # # def get_service(self, name, resolve=False): # # "Query and resolve a service" # # return self.catalog.get_service(name, resolve=resolve) # def list_resources(self): # "List all resources" # return self.catalog.resources def list_services(self): "List all services" return self.catalog.services ret = {svc.name: svc.list_cmds() for svc in self.catalog.services.values()} return ret def shell_enable(self): "Enable shell" return self.catalog.shell_enable() def shell_disable(self): "Disable shell" return self.catalog.shell_disable()