def load_config(cfg_path, find_config_files, config_loader, loader_callback=None): '''Load configuration file and setup watches Watches are only set up if loader_callback is not None. :param str cfg_path: Path for configuration file that should be loaded. :param function find_config_files: Function that finds configuration file. Check out the description of the return value of ``generate_config_finder`` function. :param ConfigLoader config_loader: Configuration file loader class instance. :param function loader_callback: Function that will be called by config_loader when change to configuration file is detected. :return: Configuration file contents. ''' found_files = find_config_files(cfg_path, config_loader, loader_callback) ret = None for path in found_files: if loader_callback: config_loader.register(loader_callback, path) if ret is None: ret = config_loader.load(path) else: mergedicts(ret, config_loader.load(path)) return ret
def load_theme_config(self, name): r = super(PDBPowerline, self).load_theme_config(name) theme_overrides = os.environ.get('POWERLINE_THEME_OVERRIDES') if theme_overrides: theme_overrides_dict = mergeargs(parse_override_var(theme_overrides)) if name in theme_overrides_dict: mergedicts(r, theme_overrides_dict[name]) return r
def load_theme_config(self, name): r = super(PDBPowerline, self).load_theme_config(name) theme_overrides = os.environ.get('POWERLINE_THEME_OVERRIDES') if theme_overrides: theme_overrides_dict = mergeargs( parse_override_var(theme_overrides)) if name in theme_overrides_dict: mergedicts(r, theme_overrides_dict[name]) return r
def _override_from(config, override_varname, key=None): try: overrides = vim_getvar(override_varname) except KeyError: return config if key is not None: try: overrides = overrides[key] except KeyError: return config mergedicts(config, overrides) return config
def test_mergedicts(self): d = {} mergedicts(d, {'abc': {'def': 'ghi'}}) self.assertEqual(d, {'abc': {'def': 'ghi'}}) mergedicts(d, {'abc': {'def': {'ghi': 'jkl'}}}) self.assertEqual(d, {'abc': {'def': {'ghi': 'jkl'}}}) mergedicts(d, {}) self.assertEqual(d, {'abc': {'def': {'ghi': 'jkl'}}}) mergedicts(d, {'abc': {'mno': 'pqr'}}) self.assertEqual(d, {'abc': {'def': {'ghi': 'jkl'}, 'mno': 'pqr'}}) mergedicts(d, {'abc': {'def': REMOVE_THIS_KEY}}) self.assertEqual(d, {'abc': {'mno': 'pqr'}})
def add_local_theme(self, key, config): '''Add local themes at runtime (during vim session). :param str key: Matcher name (in format ``{matcher_module}.{module_attribute}`` or ``{module_attribute}`` if ``{matcher_module}`` is ``powerline.matchers.vim``). Function pointed by ``{module_attribute}`` should be hashable and accept a dictionary with information about current buffer and return boolean value indicating whether current window matched conditions. See also :ref:`local_themes key description <config-ext-local_themes>`. :param dict config: :ref:`Theme <config-themes>` dictionary. :return: ``True`` if theme was added successfully and ``False`` if theme with the same matcher already exists. ''' self.update_renderer() matcher = self.get_matcher(key) theme_config = {} for cfg_path in self.theme_levels: try: lvl_config = self.load_config(cfg_path, 'theme') except IOError: pass else: mergedicts(theme_config, lvl_config) mergedicts(theme_config, config) try: self.renderer.add_local_theme(matcher, {'config': theme_config}) except KeyError: return False else: # Hack for local themes support: when reloading modules it is not # guaranteed that .add_local_theme will be called once again, so # this function arguments will be saved here for calling from # .do_setup(). self.setup_kwargs.setdefault('_local_themes', []).append( (key, config)) return True
def _load_hierarhical_config(self, cfg_type, levels, ignore_levels): '''Load and merge multiple configuration files :param str cfg_type: Type of the loaded configuration files (e.g. ``colorscheme``, ``theme``). :param list levels: Configuration names resembling levels in hierarchy, sorted by priority. Configuration file names with higher priority should go last. :param set ignore_levels: If only files listed in this variable are present then configuration file is considered not loaded: at least one file on the level not listed in this variable must be present. ''' config = {} loaded = 0 exceptions = [] for i, cfg_path in enumerate(levels): try: lvl_config = self.load_config(cfg_path, cfg_type) except IOError as e: if sys.version_info < (3, ): tb = sys.exc_info()[2] exceptions.append((e, tb)) else: exceptions.append(e) else: if i not in ignore_levels: loaded += 1 mergedicts(config, lvl_config) if not loaded: for exception in exceptions: if type(exception) is tuple: e = exception[0] else: e = exception self.exception('Failed to load %s: {0}' % cfg_type, e, exception=exception) raise e return config
def add_local_theme(self, key, config): '''Add local themes at runtime (during vim session). :param str key: Matcher name (in format ``{matcher_module}.{module_attribute}`` or ``{module_attribute}`` if ``{matcher_module}`` is ``powerline.matchers.vim``). Function pointed by ``{module_attribute}`` should be hashable and accept a dictionary with information about current buffer and return boolean value indicating whether current window matched conditions. See also :ref:`local_themes key description <config-ext-local_themes>`. :param dict config: :ref:`Theme <config-themes>` dictionary. :return: ``True`` if theme was added successfully and ``False`` if theme with the same matcher already exists. ''' self.update_renderer() matcher = self.get_matcher(key) theme_config = {} for cfg_path in self.theme_levels: try: lvl_config = self.load_config(cfg_path, 'theme') except IOError: pass else: mergedicts(theme_config, lvl_config) mergedicts(theme_config, config) try: self.renderer.add_local_theme(matcher, {'config': theme_config}) except KeyError: return False else: # Hack for local themes support: when reloading modules it is not # guaranteed that .add_local_theme will be called once again, so # this function arguments will be saved here for calling from # .do_setup(). self.setup_kwargs.setdefault('_local_themes', []).append((key, config)) return True
def _load_hierarhical_config(self, cfg_type, levels, ignore_levels): '''Load and merge multiple configuration files :param str cfg_type: Type of the loaded configuration files (e.g. ``colorscheme``, ``theme``). :param list levels: Configuration names resembling levels in hierarchy, sorted by priority. Configuration file names with higher priority should go last. :param set ignore_levels: If only files listed in this variable are present then configuration file is considered not loaded: at least one file on the level not listed in this variable must be present. ''' config = {} loaded = 0 exceptions = [] for i, cfg_path in enumerate(levels): try: lvl_config = self.load_config(cfg_path, cfg_type) except IOError as e: if sys.version_info < (3,): tb = sys.exc_info()[2] exceptions.append((e, tb)) else: exceptions.append(e) else: if i not in ignore_levels: loaded += 1 mergedicts(config, lvl_config) if not loaded: for exception in exceptions: if type(exception) is tuple: e = exception[0] else: e = exception self.exception('Failed to load %s: {0}' % cfg_type, e, exception=exception) raise e return config
def load_theme_config(self, name): r = super(ShellPowerline, self).load_theme_config(name) if self.args.theme_override and name in self.args.theme_override: mergedicts(r, self.args.theme_override[name]) return r
def load_theme_config(self, name): r = super(IPythonPowerline, self).load_theme_config(name) if name in self.theme_overrides: mergedicts(r, self.theme_overrides[name]) return r
def load_main_config(self): r = super(IPythonPowerline, self).load_main_config() if self.config_overrides: mergedicts(r, self.config_overrides) return r
def create_renderer(self, load_main=False, load_colors=False, load_colorscheme=False, load_theme=False): '''(Re)create renderer object. Can be used after Powerline object was successfully initialized. If any of the below parameters except ``load_main`` is True renderer object will be recreated. :param bool load_main: Determines whether main configuration file (:file:`config.json`) should be loaded. If appropriate configuration changes implies ``load_colorscheme`` and ``load_theme`` and recreation of renderer object. Won’t trigger recreation if only unrelated configuration changed. :param bool load_colors: Determines whether colors configuration from :file:`colors.json` should be (re)loaded. :param bool load_colorscheme: Determines whether colorscheme configuration should be (re)loaded. :param bool load_theme: Determines whether theme configuration should be reloaded. ''' common_config_differs = False ext_config_differs = False if load_main: self._purge_configs('main') config = self.load_main_config() self.common_config = finish_common_config(self.get_encoding(), config['common']) if self.common_config != self.prev_common_config: common_config_differs = True load_theme = (load_theme or not self.prev_common_config or self.prev_common_config['default_top_theme'] != self.common_config['default_top_theme']) self.prev_common_config = self.common_config self.import_paths = self.common_config['paths'] if not self.logger: self.logger = self.create_logger() if not self.pl: self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext) self.config_loader.pl = self.pl if not self.run_once: self.config_loader.set_watcher(self.common_config['watcher']) self.get_module_attr = gen_module_attr_getter(self.pl, self.import_paths, self.imported_modules) mergedicts(self.renderer_options, dict( pl=self.pl, term_truecolor=self.common_config['term_truecolor'], term_escape_style=self.common_config['term_escape_style'], ambiwidth=self.common_config['ambiwidth'], tmux_escape=self.common_config['additional_escapes'] == 'tmux', screen_escape=self.common_config['additional_escapes'] == 'screen', theme_kwargs={ 'ext': self.ext, 'common_config': self.common_config, 'run_once': self.run_once, 'shutdown_event': self.shutdown_event, 'get_module_attr': self.get_module_attr, }, )) if not self.run_once and self.common_config['reload_config']: interval = self.common_config['interval'] self.config_loader.set_interval(interval) self.run_loader_update = (interval is None) if interval is not None and not self.config_loader.is_alive(): self.config_loader.start() self.ext_config = config['ext'][self.ext] top_theme = ( self.ext_config.get('top_theme') or self.common_config['default_top_theme'] ) self.theme_levels = ( os.path.join('themes', top_theme), os.path.join('themes', self.ext, '__main__'), ) self.renderer_options['theme_kwargs']['top_theme'] = top_theme if self.ext_config != self.prev_ext_config: ext_config_differs = True if ( not self.prev_ext_config or self.ext_config.get('components') != self.prev_ext_config.get('components') ): self.setup_components(self.ext_config.get('components')) if ( not self.prev_ext_config or self.ext_config.get('local_themes') != self.prev_ext_config.get('local_themes') ): self.renderer_options['local_themes'] = self.get_local_themes(self.ext_config.get('local_themes')) load_colorscheme = ( load_colorscheme or not self.prev_ext_config or self.prev_ext_config['colorscheme'] != self.ext_config['colorscheme'] ) load_theme = ( load_theme or not self.prev_ext_config or self.prev_ext_config['theme'] != self.ext_config['theme'] ) self.prev_ext_config = self.ext_config create_renderer = load_colors or load_colorscheme or load_theme or common_config_differs or ext_config_differs if load_colors: self._purge_configs('colors') self.colors_config = self.load_colors_config() if load_colorscheme or load_colors: self._purge_configs('colorscheme') if load_colorscheme: self.colorscheme_config = self.load_colorscheme_config(self.ext_config['colorscheme']) self.renderer_options['theme_kwargs']['colorscheme'] = ( Colorscheme(self.colorscheme_config, self.colors_config)) if load_theme: self._purge_configs('theme') self.renderer_options['theme_config'] = self.load_theme_config(self.ext_config.get('theme', 'default')) if create_renderer: Renderer = self.get_module_attr(self.renderer_module, 'renderer') if not Renderer: if hasattr(self, 'renderer'): return else: raise ImportError('Failed to obtain renderer') # Renderer updates configuration file via segments’ .startup thus it # should be locked to prevent state when configuration was updated, # but .render still uses old renderer. try: renderer = Renderer(**self.renderer_options) except Exception as e: self.exception('Failed to construct renderer object: {0}', str(e)) if not hasattr(self, 'renderer'): raise else: self.renderer = renderer
def load_main_config(self): r = super(PDBPowerline, self).load_main_config() config_overrides = os.environ.get('POWERLINE_CONFIG_OVERRIDES') if config_overrides: mergedicts(r, mergeargs(parse_override_var(config_overrides))) return r
def create_renderer(self, load_main=False, load_colors=False, load_colorscheme=False, load_theme=False): '''(Re)create renderer object. Can be used after Powerline object was successfully initialized. If any of the below parameters except ``load_main`` is True renderer object will be recreated. :param bool load_main: Determines whether main configuration file (:file:`config.json`) should be loaded. If appropriate configuration changes implies ``load_colorscheme`` and ``load_theme`` and recreation of renderer object. Won’t trigger recreation if only unrelated configuration changed. :param bool load_colors: Determines whether colors configuration from :file:`colors.json` should be (re)loaded. :param bool load_colorscheme: Determines whether colorscheme configuration should be (re)loaded. :param bool load_theme: Determines whether theme configuration should be reloaded. ''' common_config_differs = False ext_config_differs = False if load_main: self._purge_configs('main') config = self.load_main_config() self.common_config = finish_common_config(self.get_encoding(), config['common']) if self.common_config != self.prev_common_config: common_config_differs = True load_theme = (load_theme or not self.prev_common_config or self.prev_common_config['default_top_theme'] != self.common_config['default_top_theme']) log_keys_differ = (not self.prev_common_config or (_get_log_keys(self.prev_common_config) != _get_log_keys(self.common_config))) self.prev_common_config = self.common_config if log_keys_differ: if self.had_logger: self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext) self.get_module_attr = gen_module_attr_getter( self.pl, self.common_config['paths'], self.imported_modules) else: self.logger, self.pl, self.get_module_attr = self.create_logger( ) self.config_loader.pl = self.pl if not self.run_once: self.config_loader.set_watcher( self.common_config['watcher']) mergedicts( self.renderer_options, dict( pl=self.pl, term_truecolor=self.common_config['term_truecolor'], term_escape_style=self. common_config['term_escape_style'], ambiwidth=self.common_config['ambiwidth'], tmux_escape=self.common_config['additional_escapes'] == 'tmux', screen_escape=self.common_config['additional_escapes'] == 'screen', theme_kwargs={ 'ext': self.ext, 'common_config': self.common_config, 'run_once': self.run_once, 'shutdown_event': self.shutdown_event, 'get_module_attr': self.get_module_attr, }, )) if not self.run_once and self.common_config['reload_config']: interval = self.common_config['interval'] self.config_loader.set_interval(interval) self.run_loader_update = (interval is None) if interval is not None and not self.config_loader.is_alive( ): self.config_loader.start() self.ext_config = config['ext'][self.ext] top_theme = (self.ext_config.get('top_theme') or self.common_config['default_top_theme']) self.theme_levels = ( os.path.join('themes', top_theme), os.path.join('themes', self.ext, '__main__'), ) self.renderer_options['theme_kwargs']['top_theme'] = top_theme if self.ext_config != self.prev_ext_config: ext_config_differs = True if (not self.prev_ext_config or self.ext_config.get('components') != self.prev_ext_config.get('components')): self.setup_components(self.ext_config.get('components')) if (not self.prev_ext_config or self.ext_config.get('local_themes') != self.prev_ext_config.get('local_themes')): self.renderer_options[ 'local_themes'] = self.get_local_themes( self.ext_config.get('local_themes')) self.update_interval = self.ext_config.get( 'update_interval', 2) load_colorscheme = (load_colorscheme or not self.prev_ext_config or self.prev_ext_config['colorscheme'] != self.ext_config['colorscheme']) load_theme = (load_theme or not self.prev_ext_config or self.prev_ext_config['theme'] != self.ext_config['theme']) self.prev_ext_config = self.ext_config create_renderer = load_colors or load_colorscheme or load_theme or common_config_differs or ext_config_differs if load_colors: self._purge_configs('colors') self.colors_config = self.load_colors_config() if load_colorscheme or load_colors: self._purge_configs('colorscheme') if load_colorscheme: self.colorscheme_config = self.load_colorscheme_config( self.ext_config['colorscheme']) self.renderer_options['theme_kwargs']['colorscheme'] = ( Colorscheme(self.colorscheme_config, self.colors_config)) if load_theme: self._purge_configs('theme') self.renderer_options['theme_config'] = self.load_theme_config( self.ext_config.get('theme', 'default')) if create_renderer: Renderer = self.get_module_attr(self.renderer_module, 'renderer') if not Renderer: if hasattr(self, 'renderer'): return else: raise ImportError('Failed to obtain renderer') # Renderer updates configuration file via segments’ .startup thus it # should be locked to prevent state when configuration was updated, # but .render still uses old renderer. try: renderer = Renderer(**self.renderer_options) except Exception as e: self.exception('Failed to construct renderer object: {0}', str(e)) if not hasattr(self, 'renderer'): raise else: self.renderer = renderer
def load_main_config(self): r = super(ShellPowerline, self).load_main_config() if self.args.config_override: mergedicts(r, self.args.config_override) return r
def create_renderer(self, load_main=False, load_colors=False, load_colorscheme=False, load_theme=False): """(Re)create renderer object. Can be used after Powerline object was successfully initialized. If any of the below parameters except ``load_main`` is True renderer object will be recreated. :param bool load_main: Determines whether main configuration file (:file:`config.json`) should be loaded. If appropriate configuration changes implies ``load_colorscheme`` and ``load_theme`` and recreation of renderer object. Won’t trigger recreation if only unrelated configuration changed. :param bool load_colors: Determines whether colors configuration from :file:`colors.json` should be (re)loaded. :param bool load_colorscheme: Determines whether colorscheme configuration should be (re)loaded. :param bool load_theme: Determines whether theme configuration should be reloaded. """ common_config_differs = False ext_config_differs = False if load_main: self._purge_configs("main") config = self.load_main_config() self.common_config = finish_common_config(self.get_encoding(), config["common"]) if self.common_config != self.prev_common_config: common_config_differs = True load_theme = ( load_theme or not self.prev_common_config or self.prev_common_config["default_top_theme"] != self.common_config["default_top_theme"] ) log_keys_differ = not self.prev_common_config or ( _get_log_keys(self.prev_common_config) != _get_log_keys(self.common_config) ) self.prev_common_config = self.common_config if log_keys_differ: if self.had_logger: self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext) self.get_module_attr = gen_module_attr_getter( self.pl, self.common_config["paths"], self.imported_modules ) else: self.logger, self.pl, self.get_module_attr = self.create_logger() self.config_loader.pl = self.pl if not self.run_once: self.config_loader.set_watcher(self.common_config["watcher"]) mergedicts( self.renderer_options, dict( pl=self.pl, term_truecolor=self.common_config["term_truecolor"], term_escape_style=self.common_config["term_escape_style"], ambiwidth=self.common_config["ambiwidth"], tmux_escape=self.common_config["additional_escapes"] == "tmux", screen_escape=self.common_config["additional_escapes"] == "screen", theme_kwargs={ "ext": self.ext, "common_config": self.common_config, "run_once": self.run_once, "shutdown_event": self.shutdown_event, "get_module_attr": self.get_module_attr, }, ), ) if not self.run_once and self.common_config["reload_config"]: interval = self.common_config["interval"] self.config_loader.set_interval(interval) self.run_loader_update = interval is None if interval is not None and not self.config_loader.is_alive(): self.config_loader.start() self.ext_config = config["ext"][self.ext] top_theme = self.ext_config.get("top_theme") or self.common_config["default_top_theme"] self.theme_levels = (os.path.join("themes", top_theme), os.path.join("themes", self.ext, "__main__")) self.renderer_options["theme_kwargs"]["top_theme"] = top_theme if self.ext_config != self.prev_ext_config: ext_config_differs = True if not self.prev_ext_config or self.ext_config.get("components") != self.prev_ext_config.get( "components" ): self.setup_components(self.ext_config.get("components")) if not self.prev_ext_config or self.ext_config.get("local_themes") != self.prev_ext_config.get( "local_themes" ): self.renderer_options["local_themes"] = self.get_local_themes(self.ext_config.get("local_themes")) load_colorscheme = ( load_colorscheme or not self.prev_ext_config or self.prev_ext_config["colorscheme"] != self.ext_config["colorscheme"] ) load_theme = ( load_theme or not self.prev_ext_config or self.prev_ext_config["theme"] != self.ext_config["theme"] ) self.prev_ext_config = self.ext_config create_renderer = load_colors or load_colorscheme or load_theme or common_config_differs or ext_config_differs if load_colors: self._purge_configs("colors") self.colors_config = self.load_colors_config() if load_colorscheme or load_colors: self._purge_configs("colorscheme") if load_colorscheme: self.colorscheme_config = self.load_colorscheme_config(self.ext_config["colorscheme"]) self.renderer_options["theme_kwargs"]["colorscheme"] = Colorscheme( self.colorscheme_config, self.colors_config ) if load_theme: self._purge_configs("theme") self.renderer_options["theme_config"] = self.load_theme_config(self.ext_config.get("theme", "default")) if create_renderer: Renderer = self.get_module_attr(self.renderer_module, "renderer") if not Renderer: if hasattr(self, "renderer"): return else: raise ImportError("Failed to obtain renderer") # Renderer updates configuration file via segments’ .startup thus it # should be locked to prevent state when configuration was updated, # but .render still uses old renderer. try: renderer = Renderer(**self.renderer_options) except Exception as e: self.exception("Failed to construct renderer object: {0}", str(e)) if not hasattr(self, "renderer"): raise else: self.renderer = renderer