def test_update_missing(self): loader = ConfigLoader(run_once=True) fpath = os.path.join(FILE_ROOT, 'file.json') self.assertRaises(IOError, loader.load, fpath) loader.register_missing(check_file, on_load, fpath) loader.update() # This line must not raise IOError with FSTree({'file': {'test': 1}}, root=FILE_ROOT): loader.update() self.assertEqual(loader.load(fpath), {'test': 1}) self.assertEqual(loaded.pop_all(), [fpath])
def init(self, ext, renderer_module=None, run_once=False, logger=None, use_daemon_threads=True, shutdown_event=None, config_loader=None): '''Do actual initialization. __init__ function only stores the arguments and runs this function. This function exists for powerline to be able to reload itself: it is easier to make ``__init__`` store arguments and call overriddable ``init`` than tell developers that each time they override Powerline.__init__ in subclasses they must store actual arguments. ''' self.ext = ext self.run_once = run_once self.logger = logger self.use_daemon_threads = use_daemon_threads if not renderer_module: self.renderer_module = 'powerline.renderers.' + ext elif '.' not in renderer_module: self.renderer_module = 'powerline.renderers.' + renderer_module elif renderer_module.startswith('.'): self.renderer_module = 'powerline.renderers.' + ext + renderer_module elif renderer_module.endswith('.'): self.renderer_module = renderer_module[:-1] else: self.renderer_module = renderer_module self.find_config_files = generate_config_finder(self.get_config_paths) self.cr_kwargs_lock = Lock() self.cr_kwargs = {} self.cr_callbacks = {} for key in ('main', 'colors', 'colorscheme', 'theme'): self.cr_kwargs['load_' + key] = True self.cr_callbacks[key] = _generate_change_callback( self.cr_kwargs_lock, 'load_' + key, self.cr_kwargs) self.shutdown_event = shutdown_event or Event() self.config_loader = config_loader or ConfigLoader( shutdown_event=self.shutdown_event, run_once=run_once) self.run_loader_update = False self.renderer_options = {} self.prev_common_config = None self.prev_ext_config = None self.pl = None self.setup_args = () self.setup_kwargs = {} self.imported_modules = set()
def get_powerline(**kwargs): watcher = Watcher() pl = TestPowerline(ext='test', renderer_module='tests.lib.config_mock', logger=Logger(), config_loader=ConfigLoader( load=load_json_config, watcher=watcher, run_once=kwargs.get('run_once')), **kwargs) pl._watcher = watcher return pl
def __init__(self, ext, renderer_module=None, run_once=False, logger=None, use_daemon_threads=True, shutdown_event=None, config_loader=None): self.ext = ext self.renderer_module = renderer_module or ext self.run_once = run_once self.logger = logger self.use_daemon_threads = use_daemon_threads if '.' not in self.renderer_module: self.renderer_module = 'powerline.renderers.' + self.renderer_module elif self.renderer_module[-1] == '.': self.renderer_module = self.renderer_module[:-1] config_paths = self.get_config_paths() self.find_config_file = lambda cfg_path: find_config_file( config_paths, cfg_path) self.cr_kwargs_lock = Lock() self.create_renderer_kwargs = { 'load_main': True, 'load_colors': True, 'load_colorscheme': True, 'load_theme': True, } self.shutdown_event = shutdown_event or Event() self.config_loader = config_loader or ConfigLoader( shutdown_event=self.shutdown_event) self.run_loader_update = False self.renderer_options = {} self.prev_common_config = None self.prev_ext_config = None self.pl = None
def get_main_config(args): find_config_files = generate_config_finder() config_loader = ConfigLoader(run_once=True) return load_config('config', find_config_files, config_loader)
def check(paths=None, debug=False, echoerr=echoerr, require_ext=None): '''Check configuration sanity :param list paths: Paths from which configuration should be loaded. :param bool debug: Determines whether some information useful for debugging linter should be output. :param function echoerr: Function that will be used to echo the error(s). Should accept four optional keyword parameters: ``problem`` and ``problem_mark``, and ``context`` and ``context_mark``. :param str require_ext: Require configuration for some extension to be present. :return: ``False`` if user configuration seems to be completely sane and ``True`` if some problems were found. ''' hadproblem = False register_common_names() search_paths = paths or get_config_paths() find_config_files = generate_config_finder(lambda: search_paths) logger = logging.getLogger('powerline-lint') logger.setLevel(logging.DEBUG if debug else logging.ERROR) logger.addHandler(logging.StreamHandler()) ee = EchoErr(echoerr, logger) if require_ext: used_main_spec = main_spec.copy() try: used_main_spec['ext'][require_ext].required() except KeyError: used_main_spec['ext'][require_ext] = ext_spec() else: used_main_spec = main_spec lhadproblem = [False] load_json_config = generate_json_config_loader(lhadproblem) config_loader = ConfigLoader(run_once=True, load=load_json_config) lists = { 'colorschemes': set(), 'themes': set(), 'exts': set(), } found_dir = { 'themes': False, 'colorschemes': False, } config_paths = defaultdict(lambda: defaultdict(dict)) loaded_configs = defaultdict(lambda: defaultdict(dict)) for d in chain( find_all_ext_config_files(search_paths, 'colorschemes'), find_all_ext_config_files(search_paths, 'themes'), ): if d['error']: hadproblem = True ee(problem=d['error']) continue if d['hadproblem']: hadproblem = True if d['ext']: found_dir[d['type']] = True lists['exts'].add(d['ext']) if d['name'] == '__main__': pass elif d['name'].startswith('__') or d['name'].endswith('__'): hadproblem = True ee(problem= 'File name is not supposed to start or end with “__”: {0}'. format(d['path'])) else: lists[d['type']].add(d['name']) config_paths[d['type']][d['ext']][d['name']] = d['path'] loaded_configs[d['type']][d['ext']][d['name']] = d['config'] else: config_paths[d['type']][d['name']] = d['path'] loaded_configs[d['type']][d['name']] = d['config'] for typ in ('themes', 'colorschemes'): if not found_dir[typ]: hadproblem = True ee(problem='Subdirectory {0} was not found in paths {1}'.format( typ, ', '.join(search_paths))) diff = set(config_paths['colorschemes']) - set(config_paths['themes']) if diff: hadproblem = True for ext in diff: typ = 'colorschemes' if ext in config_paths['themes'] else 'themes' if not config_paths['top_' + typ] or typ == 'themes': ee(problem='{0} extension {1} not present in {2}'.format( ext, 'configuration' if ( ext in loaded_configs['themes'] and ext in loaded_configs['colorschemes']) else 'directory', typ, )) try: main_config = load_config('config', find_config_files, config_loader) except IOError: main_config = {} ee(problem='Configuration file not found: config.json') hadproblem = True except MarkedError as e: main_config = {} ee(problem=str(e)) hadproblem = True else: if used_main_spec.match(main_config, data={ 'configs': config_paths, 'lists': lists }, context=Context(main_config), echoerr=ee)[1]: hadproblem = True import_paths = [ os.path.expanduser(path) for path in main_config.get('common', {}).get('paths', []) ] try: colors_config = load_config('colors', find_config_files, config_loader) except IOError: colors_config = {} ee(problem='Configuration file not found: colors.json') hadproblem = True except MarkedError as e: colors_config = {} ee(problem=str(e)) hadproblem = True else: if colors_spec.match(colors_config, context=Context(colors_config), echoerr=ee)[1]: hadproblem = True if lhadproblem[0]: hadproblem = True top_colorscheme_configs = dict(loaded_configs['top_colorschemes']) data = { 'ext': None, 'top_colorscheme_configs': top_colorscheme_configs, 'ext_colorscheme_configs': {}, 'colors_config': colors_config } for colorscheme, config in loaded_configs['top_colorschemes'].items(): data['colorscheme'] = colorscheme if top_colorscheme_spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True ext_colorscheme_configs = dict2(loaded_configs['colorschemes']) for ext, econfigs in ext_colorscheme_configs.items(): data = { 'ext': ext, 'top_colorscheme_configs': top_colorscheme_configs, 'ext_colorscheme_configs': ext_colorscheme_configs, 'colors_config': colors_config, } for colorscheme, config in econfigs.items(): data['colorscheme'] = colorscheme if ext == 'vim': spec = vim_colorscheme_spec elif ext == 'shell': spec = shell_colorscheme_spec elif ext == 'ipython': spec = ipython_colorscheme_spec else: spec = top_colorscheme_spec if spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True colorscheme_configs = {} for ext in lists['exts']: colorscheme_configs[ext] = {} for colorscheme in lists['colorschemes']: econfigs = ext_colorscheme_configs[ext] ecconfigs = econfigs.get(colorscheme) mconfigs = ( top_colorscheme_configs.get(colorscheme), econfigs.get('__main__'), ecconfigs, ) if not (mconfigs[0] or mconfigs[2]): continue config = None for mconfig in mconfigs: if not mconfig: continue if config: config = mergedicts_copy(config, mconfig) else: config = mconfig colorscheme_configs[ext][colorscheme] = config theme_configs = dict2(loaded_configs['themes']) top_theme_configs = dict(loaded_configs['top_themes']) for ext, configs in theme_configs.items(): data = { 'ext': ext, 'colorscheme_configs': colorscheme_configs, 'import_paths': import_paths, 'main_config': main_config, 'top_themes': top_theme_configs, 'ext_theme_configs': configs, 'colors_config': colors_config } for theme, config in configs.items(): data['theme'] = theme if theme == '__main__': data['theme_type'] = 'main' spec = main_theme_spec else: data['theme_type'] = 'regular' spec = theme_spec if spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True for top_theme, config in top_theme_configs.items(): data = { 'ext': None, 'colorscheme_configs': colorscheme_configs, 'import_paths': import_paths, 'main_config': main_config, 'theme_configs': theme_configs, 'ext_theme_configs': None, 'colors_config': colors_config } data['theme_type'] = 'top' data['theme'] = top_theme if top_theme_spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True return hadproblem
def check(paths=None, debug=False, echoerr=echoerr, require_ext=None): '''Check configuration sanity :param list paths: Paths from which configuration should be loaded. :param bool debug: Determines whether some information useful for debugging linter should be output. :param function echoerr: Function that will be used to echo the error(s). Should accept four optional keyword parameters: ``problem`` and ``problem_mark``, and ``context`` and ``context_mark``. :param str require_ext: Require configuration for some extension to be present. :return: ``False`` if user configuration seems to be completely sane and ``True`` if some problems were found. ''' register_common_names() search_paths = paths or get_config_paths() find_config_files = generate_config_finder(lambda: search_paths) logger = logging.getLogger('powerline-lint') logger.setLevel(logging.DEBUG if debug else logging.ERROR) logger.addHandler(logging.StreamHandler()) ee = EchoErr(echoerr, logger) if require_ext: used_main_spec = main_spec.copy() try: used_main_spec['ext'][require_ext].required() except KeyError: used_main_spec['ext'][require_ext] = ext_spec() else: used_main_spec = main_spec lhadproblem = [False] load_json_config = generate_json_config_loader(lhadproblem) config_loader = ConfigLoader(run_once=True, load=load_json_config) paths = { 'themes': defaultdict(lambda: []), 'colorschemes': defaultdict(lambda: []), 'top_colorschemes': [], 'top_themes': [], } lists = { 'colorschemes': set(), 'themes': set(), 'exts': set(), } for path in reversed(search_paths): for typ in ('themes', 'colorschemes'): d = os.path.join(path, typ) if os.path.isdir(d): for subp in os.listdir(d): extpath = os.path.join(d, subp) if os.path.isdir(extpath): lists['exts'].add(subp) paths[typ][subp].append(extpath) elif extpath.endswith('.json'): name = subp[:-5] if name != '__main__': lists[typ].add(name) paths['top_' + typ].append(extpath) else: hadproblem = True ee(problem= 'Path {0} is supposed to be a directory, but it is not'. format(d)) hadproblem = False configs = defaultdict(lambda: defaultdict(lambda: {})) for typ in ('themes', 'colorschemes'): for ext in paths[typ]: for d in paths[typ][ext]: for subp in os.listdir(d): if subp.endswith('.json'): name = subp[:-5] if name != '__main__': lists[typ].add(name) if name.startswith('__') or name.endswith('__'): hadproblem = True ee(problem= 'File name is not supposed to start or end with “__”: {0}' .format(os.path.join(d, subp))) configs[typ][ext][name] = os.path.join(d, subp) for path in paths['top_' + typ]: name = os.path.basename(path)[:-5] configs['top_' + typ][name] = path diff = set(configs['colorschemes']) - set(configs['themes']) if diff: hadproblem = True for ext in diff: typ = 'colorschemes' if ext in configs['themes'] else 'themes' if not configs['top_' + typ] or typ == 'themes': ee(problem='{0} extension {1} not present in {2}'.format( ext, 'configuration' if ( ext in paths['themes'] and ext in paths['colorschemes'] ) else 'directory', typ, )) try: main_config = load_config('config', find_config_files, config_loader) except IOError: main_config = {} ee(problem='Configuration file not found: config.json') hadproblem = True except MarkedError as e: main_config = {} ee(problem=str(e)) hadproblem = True else: if used_main_spec.match(main_config, data={ 'configs': configs, 'lists': lists }, context=Context(main_config), echoerr=ee)[1]: hadproblem = True import_paths = [ os.path.expanduser(path) for path in main_config.get('common', {}).get('paths', []) ] try: colors_config = load_config('colors', find_config_files, config_loader) except IOError: colors_config = {} ee(problem='Configuration file not found: colors.json') hadproblem = True except MarkedError as e: colors_config = {} ee(problem=str(e)) hadproblem = True else: if colors_spec.match(colors_config, context=Context(colors_config), echoerr=ee)[1]: hadproblem = True if lhadproblem[0]: hadproblem = True top_colorscheme_configs = {} data = { 'ext': None, 'top_colorscheme_configs': top_colorscheme_configs, 'ext_colorscheme_configs': {}, 'colors_config': colors_config } for colorscheme, cfile in configs['top_colorschemes'].items(): with open_file(cfile) as config_file_fp: try: config, lhadproblem = load(config_file_fp) except MarkedError as e: ee(problem=str(e)) hadproblem = True continue if lhadproblem: hadproblem = True top_colorscheme_configs[colorscheme] = config data['colorscheme'] = colorscheme if top_colorscheme_spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True ext_colorscheme_configs = defaultdict(lambda: {}) for ext in configs['colorschemes']: for colorscheme, cfile in configs['colorschemes'][ext].items(): with open_file(cfile) as config_file_fp: try: config, lhadproblem = load(config_file_fp) except MarkedError as e: ee(problem=str(e)) hadproblem = True continue if lhadproblem: hadproblem = True ext_colorscheme_configs[ext][colorscheme] = config for ext, econfigs in ext_colorscheme_configs.items(): data = { 'ext': ext, 'top_colorscheme_configs': top_colorscheme_configs, 'ext_colorscheme_configs': ext_colorscheme_configs, 'colors_config': colors_config, } for colorscheme, config in econfigs.items(): data['colorscheme'] = colorscheme if ext == 'vim': spec = vim_colorscheme_spec elif ext == 'shell': spec = shell_colorscheme_spec else: spec = colorscheme_spec if spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True colorscheme_configs = {} for ext in lists['exts']: colorscheme_configs[ext] = {} for colorscheme in lists['colorschemes']: econfigs = ext_colorscheme_configs[ext] ecconfigs = econfigs.get(colorscheme) mconfigs = ( top_colorscheme_configs.get(colorscheme), econfigs.get('__main__'), ecconfigs, ) config = None for mconfig in mconfigs: if not mconfig: continue if config: config = mergedicts_copy(config, mconfig) else: config = mconfig colorscheme_configs[colorscheme] = config theme_configs = defaultdict(lambda: {}) for ext in configs['themes']: for theme, sfile in configs['themes'][ext].items(): with open_file(sfile) as config_file_fp: try: config, lhadproblem = load(config_file_fp) except MarkedError as e: ee(problem=str(e)) hadproblem = True continue if lhadproblem: hadproblem = True theme_configs[ext][theme] = config top_theme_configs = {} for top_theme, top_theme_file in configs['top_themes'].items(): with open_file(top_theme_file) as config_file_fp: try: config, lhadproblem = load(config_file_fp) except MarkedError as e: ee(problem=str(e)) hadproblem = True continue if lhadproblem: hadproblem = True top_theme_configs[top_theme] = config for ext, configs in theme_configs.items(): data = { 'ext': ext, 'colorscheme_configs': colorscheme_configs, 'import_paths': import_paths, 'main_config': main_config, 'top_themes': top_theme_configs, 'ext_theme_configs': configs, 'colors_config': colors_config } for theme, config in configs.items(): data['theme'] = theme if theme == '__main__': data['theme_type'] = 'main' spec = main_theme_spec else: data['theme_type'] = 'regular' spec = theme_spec if spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True for top_theme, config in top_theme_configs.items(): data = { 'ext': ext, 'colorscheme_configs': colorscheme_configs, 'import_paths': import_paths, 'main_config': main_config, 'theme_configs': theme_configs, 'ext_theme_configs': configs, 'colors_config': colors_config } data['theme_type'] = 'top' data['theme'] = top_theme if top_theme_spec.match(config, context=Context(config), data=data, echoerr=ee)[1]: hadproblem = True return hadproblem