def check_log_file_level(this_level, data, context, echoerr): '''Check handler level specified in :ref:`log_file key <config-common-log>` This level must be greater or equal to the level in :ref:`log_level key <config-common-log_level>`. ''' havemarks(this_level) hadproblem = False top_level = context[0][1].get('common', {}).get('log_level', 'WARNING') top_level_str = top_level top_level_mark = getattr(top_level, 'mark', None) if ( not isinstance(top_level, unicode) or not hasattr(logging, top_level) or not isinstance(this_level, unicode) or not hasattr(logging, this_level) ): return True, False, hadproblem top_level = getattr(logging, top_level) this_level_str = this_level this_level_mark = this_level.mark this_level = getattr(logging, this_level) if this_level < top_level: echoerr( context='Error while checking log level index (key {key})'.format( key=context.key), context_mark=this_level_mark, problem='found level that is less critical then top level ({0} < {0})'.format( this_level_str, top_level_str), problem_mark=top_level_mark, ) hadproblem = True return True, False, hadproblem
def check_logging_handler(handler_name, data, context, echoerr): havemarks(handler_name) import_paths = [os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', [])] handler_module, separator, handler_class = handler_name.rpartition('.') if not separator: handler_module = 'logging.handlers' handler_class = handler_name with WithPath(import_paths): try: handler = getattr(__import__(str(handler_module), fromlist=[str(handler_class)]), str(handler_class)) except ImportError: echoerr(context='Error while loading logger class (key {key})'.format(key=context.key), problem='failed to load module {0}'.format(handler_module), problem_mark=handler_name.mark) return True, False, True except AttributeError: echoerr(context='Error while loading logger class (key {key})'.format(key=context.key), problem='failed to load handler class {0}'.format(handler_class), problem_mark=handler_name.mark) return True, False, True if not issubclass(handler, logging.Handler): echoerr(context='Error while loading logger class (key {key})'.format(key=context.key), problem='loaded class {0} is not a logging.Handler subclass'.format(handler_class), problem_mark=handler_name.mark) return True, False, True return True, False, False
def check_either(self, value, context_mark, data, context, echoerr, start, end): '''Check that given value matches one of the given specifications :param int start: First specification index. :param int end: Specification index that is greater by 1 then last specification index. This method does not give an error if any specification from ``self.specs[start:end]`` is matched by the given value. ''' havemarks(value) new_echoerr = DelayedEchoErr(echoerr) hadproblem = False for spec in self.specs[start:end]: proceed, hadproblem = spec.match(value, value.mark, data, context, new_echoerr) if not proceed: break if not hadproblem: return True, False new_echoerr.echo_all() return False, hadproblem
def import_function(function_type, name, data, context, echoerr, module): havemarks(name, module) with WithPath(data['import_paths']): try: func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) except ImportError: echoerr(context='Error while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem='failed to import module {0}'.format(module), problem_mark=module.mark) return None except AttributeError: echoerr( context='Error while loading {0} function (key {key})'.format( function_type, key=context.key), problem='failed to load function {0} from module {1}'.format( name, module), problem_mark=name.mark) return None if not callable(func): echoerr( context='Error while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem='imported “function” {0} from module {1} is not callable'. format(name, module), problem_mark=module.mark) return None return func
def check_tuple(self, value, context_mark, data, context, echoerr, start, end): '''Check that given value is a list with items matching specifications :param int start: First specification index. :param int end: Specification index that is greater by 1 then last specification index. This method checks that each item in the value list matches specification with index ``start + item_number``. ''' havemarks(value) hadproblem = False for (i, item, spec) in zip(itertools.count(), value, self.specs[start:end]): proceed, ihadproblem = spec.match( item, value.mark, data, context.enter_item('tuple item ' + unicode(i), item), echoerr ) if ihadproblem: hadproblem = True if not proceed: return False, hadproblem return True, hadproblem
def import_function(function_type, name, data, context, echoerr, module): havemarks(name, module) with WithPath(data['import_paths']): try: func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) except ImportError: echoerr(context='Error while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='failed to import module {0}'.format(module), problem_mark=module.mark) return None except AttributeError: echoerr(context='Error while loading {0} function (key {key})'.format(function_type, key=context.key), problem='failed to load function {0} from module {1}'.format(name, module), problem_mark=name.mark) return None if not callable(func): echoerr(context='Error while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='imported “function” {0} from module {1} is not callable'.format(name, module), problem_mark=module.mark) return None return func
def check_log_file_level(this_level, data, context, echoerr): '''Check handler level specified in :ref:`log_file key <config-common-log>` This level must be greater or equal to the level in :ref:`log_level key <config-common-log_level>`. ''' havemarks(this_level) hadproblem = False top_level = context[0][1].get('common', {}).get('log_level', 'WARNING') top_level_str = top_level top_level_mark = getattr(top_level, 'mark', None) if (not isinstance(top_level, unicode) or not hasattr(logging, top_level) or not isinstance(this_level, unicode) or not hasattr(logging, this_level)): return True, False, hadproblem top_level = getattr(logging, top_level) this_level_str = this_level this_level_mark = this_level.mark this_level = getattr(logging, this_level) if this_level < top_level: echoerr( context='Error while checking log level index (key {key})'.format( key=context.key), context_mark=this_level_mark, problem= 'found level that is less critical then top level ({0} < {0})'. format(this_level_str, top_level_str), problem_mark=top_level_mark, ) hadproblem = True return True, False, hadproblem
def check_top_theme(theme, data, context, echoerr): havemarks(theme) if theme not in data['configs']['top_themes']: echoerr(context='Error while checking extension configuration (key {key})'.format(key=context.key), context_mark=context[-2][0].mark, problem='failed to find top theme {0}'.format(theme), problem_mark=theme.mark) return True, False, True return True, False, False
def match(self, value, context_mark=None, data=None, context=(), echoerr=echoerr): """Check that given value matches this specification :return: proceed, hadproblem. """ havemarks(value) proceed, hadproblem = self.match_checks(value, context_mark, data, context, echoerr) if proceed: if self.keys or self.uspecs: for key, vali in self.keys.items(): valspec = self.specs[vali] if key in value: proceed, mhadproblem = valspec.match( value[key], value.mark, data, context.enter_key(value, key), echoerr ) if mhadproblem: hadproblem = True if not proceed: return False, hadproblem else: if not valspec.isoptional: hadproblem = True echoerr( context=self.cmsg.format(key=context.key), context_mark=None, problem="required key is missing: {0}".format(key), problem_mark=value.mark, ) for key in value.keys(): havemarks(key) if key not in self.keys: for keyfunc, vali in self.uspecs: valspec = self.specs[vali] if isinstance(keyfunc, int): spec = self.specs[keyfunc] proceed, khadproblem = spec.match(key, context_mark, data, context, echoerr) else: proceed, khadproblem = keyfunc(key, data, context, echoerr) if khadproblem: hadproblem = True if proceed: proceed, vhadproblem = valspec.match( value[key], value.mark, data, context.enter_key(value, key), echoerr ) if vhadproblem: hadproblem = True break else: hadproblem = True if self.ufailmsg: echoerr( context=self.cmsg.format(key=context.key), context_mark=None, problem=self.ufailmsg(key), problem_mark=key.mark, ) return True, hadproblem
def __new__(cls, base, context_key=None, context_value=None): if context_key is not None: assert context_value is not None assert type(base) is Context havemarks(context_key, context_value) return tuple.__new__(cls, tuple.__add__(base, ((context_key, context_value),))) else: havemarks(base) return tuple.__new__(cls, ((MarkedUnicode("", base.mark), base),))
def __new__(cls, base, context_key=None, context_value=None): if context_key is not None: assert(context_value is not None) assert(type(base) is Context) havemarks(context_key, context_value) return tuple.__new__(cls, tuple.__add__(base, ((context_key, context_value),))) else: havemarks(base) return tuple.__new__(cls, ((MarkedUnicode('', base.mark), base),))
def check_color(color, data, context, echoerr): havemarks(color) if (color not in data['colors_config'].get('colors', {}) and color not in data['colors_config'].get('gradients', {})): echoerr( context='Error while checking highlight group in colorscheme (key {key})'.format( key=context.key), problem='found unexistent color or gradient {0}'.format(color), problem_mark=color.mark ) return True, False, True return True, False, False
def check_highlight_group(hl_group, data, context, echoerr): havemarks(hl_group) r = hl_exists(hl_group, data, context, echoerr) if r: echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( hl_group, list_sep.join(r)), problem_mark=hl_group.mark ) return True, False, True return True, False, False
def check_segment_module(module, data, context, echoerr): havemarks(module) with WithPath(data['import_paths']): try: __import__(str(module)) except ImportError as e: if echoerr.logger.level >= logging.DEBUG: echoerr.logger.exception(e) echoerr(context='Error while checking segments (key {key})'.format(key=context.key), problem='failed to import module {0}'.format(module), problem_mark=module.mark) return True, False, True return True, False, False
def import_function(function_type, name, data, context, echoerr, module): havemarks(name, module) if module == 'powerline.segments.common': echoerr(context='Warning while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem='module {0} is deprecated'.format(module), problem_mark=module.mark) if module == 'powerline.segments.common.players' and name == 'now_playing': echoerr( context='Warning while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem= 'function {0}.{1} is deprecated: use {0}.{{player_name}} instead'. format(module, name), problem_mark=module.mark) with WithPath(data['import_paths']): try: func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) except ImportError: echoerr(context='Error while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem='failed to import module {0}'.format(module), problem_mark=module.mark) return None except AttributeError: echoerr( context='Error while loading {0} function (key {key})'.format( function_type, key=context.key), problem='failed to load function {0} from module {1}'.format( name, module), problem_mark=name.mark) return None if not callable(func): echoerr( context='Error while checking segments (key {key})'.format( key=context.key), context_mark=name.mark, problem='imported “function” {0} from module {1} is not callable'. format(name, module), problem_mark=module.mark) return None return func
def check_key_compatibility(segment, data, context, echoerr): havemarks(segment) segment_type = segment.get('type', MarkedUnicode('function', None)) havemarks(segment_type) if segment_type not in type_keys: echoerr(context='Error while checking segments (key {key})'.format(key=context.key), problem='found segment with unknown type {0}'.format(segment_type), problem_mark=segment_type.mark) return False, False, True hadproblem = False keys = set(segment) if not ((keys - generic_keys) < type_keys[segment_type]): unknown_keys = keys - generic_keys - type_keys[segment_type] echoerr( context='Error while checking segments (key {key})'.format(key=context.key), context_mark=context[-1][1].mark, problem='found keys not used with the current segment type: {0}'.format( list_sep.join(unknown_keys)), problem_mark=list(unknown_keys)[0].mark ) hadproblem = True if not (keys >= required_keys[segment_type]): missing_keys = required_keys[segment_type] - keys echoerr( context='Error while checking segments (key {key})'.format(key=context.key), context_mark=context[-1][1].mark, problem='found missing required keys: {0}'.format( list_sep.join(missing_keys)) ) hadproblem = True if not (segment_type == 'function' or (keys & highlight_keys)): echoerr( context='Error while checking segments (key {key})'.format(key=context.key), context_mark=context[-1][1].mark, problem=( 'found missing keys required to determine highlight group. ' 'Either highlight_groups or name key must be present' ) ) hadproblem = True return True, False, hadproblem
def hl_exists(hl_group, data, context, echoerr, allow_gradients=False): havemarks(hl_group) ext = data['ext'] if ext not in data['colorscheme_configs']: # No colorschemes. Error was already reported, no need to report it # twice return [] r = [] found = False for colorscheme, cconfig in data['colorscheme_configs'][ext].items(): if hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr): found = True else: r.append(colorscheme) if not found: pass return r
def check_matcher_func(ext, match_name, data, context, echoerr): havemarks(match_name) import_paths = [ os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', []) ] match_module, separator, match_function = match_name.rpartition('.') if not separator: match_module = 'powerline.matchers.{0}'.format(ext) match_function = match_name with WithPath(import_paths): try: func = getattr( __import__(str(match_module), fromlist=[str(match_function)]), str(match_function)) except ImportError: echoerr(context='Error while loading matcher functions', problem='failed to load module {0}'.format(match_module), problem_mark=match_name.mark) return True, False, True except AttributeError: echoerr(context='Error while loading matcher functions', problem='failed to load matcher function {0}'.format( match_function), problem_mark=match_name.mark) return True, False, True if not callable(func): echoerr(context='Error while loading matcher functions', problem='loaded “function” {0} is not callable'.format( match_function), problem_mark=match_name.mark) return True, False, True if hasattr(func, 'func_code') and hasattr(func.func_code, 'co_argcount'): if func.func_code.co_argcount != 1: echoerr( context='Error while loading matcher functions', problem=('function {0} accepts {1} arguments instead of 1. ' 'Are you sure it is the proper function?').format( match_function, func.func_code.co_argcount), problem_mark=match_name.mark) return True, False, False
def check_ext(ext, data, context, echoerr): havemarks(ext) hadsomedirs = False hadproblem = False if ext not in data['lists']['exts']: hadproblem = True echoerr(context='Error while loading {0} extension configuration'.format(ext), context_mark=ext.mark, problem='extension configuration does not exist') else: for typ in ('themes', 'colorschemes'): if ext not in data['configs'][typ] and not data['configs']['top_' + typ]: hadproblem = True echoerr(context='Error while loading {0} extension configuration'.format(ext), context_mark=ext.mark, problem='{0} configuration does not exist'.format(typ)) else: hadsomedirs = True return hadsomedirs, hadproblem
def check_highlight_groups(hl_groups, data, context, echoerr): havemarks(hl_groups) rs = [hl_exists(hl_group, data, context, echoerr) for hl_group in hl_groups] if all(rs): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem='found highlight groups list ({0}) with all groups not defined in some colorschemes'.format( list_sep.join((unicode(h) for h in hl_groups))), problem_mark=hl_groups.mark ) for r, hl_group in zip(rs, hl_groups): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( hl_group, list_sep.join(r)), problem_mark=hl_group.mark ) return True, False, True return True, False, False
def check_type(self, value, context_mark, data, context, echoerr, types): '''Check that given value matches given type(s) :param tuple types: List of accepted types. Since :py:class:`Spec` is supposed to describe JSON values only ``dict``, ``list``, ``unicode``, ``bool``, ``float`` and ``NoneType`` types make any sense. :return: proceed, hadproblem. ''' havemarks(value) if type(value.value) not in types: echoerr(context=self.cmsg.format(key=context.key), context_mark=context_mark, problem='{0!r} must be a {1} instance, not {2}'.format( value, ', '.join((t.__name__ for t in types)), type(value.value).__name__), problem_mark=value.mark) return False, True return True, False
def check_logging_handler(handler_name, data, context, echoerr): havemarks(handler_name) import_paths = [ os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', []) ] handler_module, separator, handler_class = handler_name.rpartition('.') if not separator: handler_module = 'logging.handlers' handler_class = handler_name with WithPath(import_paths): try: handler = getattr( __import__(str(handler_module), fromlist=[str(handler_class)]), str(handler_class)) except ImportError: echoerr( context='Error while loading logger class (key {key})'.format( key=context.key), problem='failed to load module {0}'.format(handler_module), problem_mark=handler_name.mark) return True, False, True except AttributeError: echoerr( context='Error while loading logger class (key {key})'.format( key=context.key), problem='failed to load handler class {0}'.format( handler_class), problem_mark=handler_name.mark) return True, False, True if not issubclass(handler, logging.Handler): echoerr(context='Error while loading logger class (key {key})'.format( key=context.key), problem='loaded class {0} is not a logging.Handler subclass'. format(handler_class), problem_mark=handler_name.mark) return True, False, True return True, False, False
def check_list(self, value, context_mark, data, context, echoerr, item_func, msg_func): '''Check that each value in the list matches given specification :param function item_func: Callable like ``func`` from :py:meth:`Spec.check_func`. Unlike ``func`` this callable is called for each value in the list and may be a :py:class:`Spec` object index. :param func msg_func: Callable like ``msg_func`` from :py:meth:`Spec.check_func`. Should accept one problematic item and is not used for :py:class:`Spec` object indicies in ``item_func`` method. :return: proceed, hadproblem. ''' havemarks(value) i = 0 hadproblem = False for item in value: havemarks(item) if isinstance(item_func, int): spec = self.specs[item_func] proceed, fhadproblem = spec.match( item, value.mark, data, context.enter_item('list item ' + unicode(i), item), echoerr ) else: proceed, echo, fhadproblem = item_func(item, data, context, echoerr) if echo and fhadproblem: echoerr(context=self.cmsg.format(key=context.key + '/list item ' + unicode(i)), context_mark=value.mark, problem=msg_func(item), problem_mark=item.mark) if fhadproblem: hadproblem = True if not proceed: return proceed, hadproblem i += 1 return True, hadproblem
def check_matcher_func(ext, match_name, data, context, echoerr): havemarks(match_name) import_paths = [os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', [])] match_module, separator, match_function = match_name.rpartition('.') if not separator: match_module = 'powerline.matchers.{0}'.format(ext) match_function = match_name with WithPath(import_paths): try: func = getattr(__import__(str(match_module), fromlist=[str(match_function)]), str(match_function)) except ImportError: echoerr(context='Error while loading matcher functions', problem='failed to load module {0}'.format(match_module), problem_mark=match_name.mark) return True, False, True except AttributeError: echoerr(context='Error while loading matcher functions', problem='failed to load matcher function {0}'.format(match_function), problem_mark=match_name.mark) return True, False, True if not callable(func): echoerr(context='Error while loading matcher functions', problem='loaded “function” {0} is not callable'.format(match_function), problem_mark=match_name.mark) return True, False, True if hasattr(func, 'func_code') and hasattr(func.func_code, 'co_argcount'): if func.func_code.co_argcount != 1: echoerr( context='Error while loading matcher functions', problem=( 'function {0} accepts {1} arguments instead of 1. ' 'Are you sure it is the proper function?' ).format(match_function, func.func_code.co_argcount), problem_mark=match_name.mark ) return True, False, False
def check_args_variant(func, args, data, context, echoerr): havemarks(args) argspec = getconfigargspec(func) present_args = set(args) all_args = set(argspec.args) required_args = set(argspec.args[:-len(argspec.defaults)]) hadproblem = False if required_args - present_args: echoerr( context='Error while checking segment arguments (key {key})'.format(key=context.key), context_mark=args.mark, problem='some of the required keys are missing: {0}'.format(list_sep.join(required_args - present_args)) ) hadproblem = True if not all_args >= present_args: echoerr(context='Error while checking segment arguments (key {key})'.format(key=context.key), context_mark=args.mark, problem='found unknown keys: {0}'.format(list_sep.join(present_args - all_args)), problem_mark=next(iter(present_args - all_args)).mark) hadproblem = True if isinstance(func, ThreadedSegment): for key in set(threaded_args_specs) & present_args: proceed, khadproblem = threaded_args_specs[key].match( args[key], args.mark, data, context.enter_key(args, key), echoerr ) if khadproblem: hadproblem = True if not proceed: return hadproblem return hadproblem
def check_type(self, value, context_mark, data, context, echoerr, types): """Check that given value matches given type(s) :param tuple types: List of accepted types. Since :py:class:`Spec` is supposed to describe JSON values only ``dict``, ``list``, ``unicode``, ``bool``, ``float`` and ``NoneType`` types make any sense. :return: proceed, hadproblem. """ havemarks(value) if type(value.value) not in types: echoerr( context=self.cmsg.format(key=context.key), context_mark=context_mark, problem="{0!r} must be a {1} instance, not {2}".format( value, ", ".join((t.__name__ for t in types)), type(value.value).__name__ ), problem_mark=value.mark, ) return False, True return True, False
def check_func(self, value, context_mark, data, context, echoerr, func, msg_func): """Check value using given function :param function func: Callable that should accept four positional parameters: #. checked value, #. ``data`` parameter with arbitrary data (supplied by top-level caller), #. current context and #. function used for echoing errors. This callable should return three values: #. determines whether ``check_func`` caller should proceed calling other checks, #. determines whether ``check_func`` should echo error on its own (it should be set to False if ``func`` echoes error itself) and #. determines whether function has found some errors in the checked value. :param function msg_func: Callable that takes checked value as the only positional parameter and returns a string that describes the problem. Only useful for small checker functions since it is ignored when second returned value is false. :return: proceed, hadproblem. """ havemarks(value) proceed, echo, hadproblem = func(value, data, context, echoerr) if echo and hadproblem: echoerr( context=self.cmsg.format(key=context.key), context_mark=context_mark, problem=msg_func(value), problem_mark=value.mark, ) return proceed, hadproblem
def check_segment_data_key(key, data, context, echoerr): havemarks(key) has_module_name = '.' in key found = False for ext, theme in list_themes(data, context): for segments in theme.get('segments', {}).values(): for segment in segments: if 'name' in segment: if key == segment['name']: found = True break else: function_name = segment.get('function') if function_name: module, function_name = get_function_strings( function_name, ((None, theme), ), ext) if has_module_name: full_name = module + '.' + function_name if key == full_name: found = True break else: if key == function_name: found = True break if found: break if found: break else: if data['theme_type'] != 'top': echoerr(context='Error while checking segment data', problem= 'found key {0} that cannot be associated with any segment'. format(key), problem_mark=key.mark) return True, False, True return True, False, False
def import_function(function_type, name, data, context, echoerr, module): havemarks(name, module) if module == 'powerline.segments.common': echoerr(context='Warning while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='module {0} is deprecated'.format(module), problem_mark=module.mark) if module == 'powerline.segments.common.players' and name == 'now_playing': echoerr(context='Warning while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='function {0}.{1} is deprecated: use {0}.{{player_name}} instead'.format(module, name), problem_mark=module.mark) with WithPath(data['import_paths']): try: func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) except ImportError: echoerr(context='Error while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='failed to import module {0}'.format(module), problem_mark=module.mark) return None except AttributeError: echoerr(context='Error while loading {0} function (key {key})'.format(function_type, key=context.key), problem='failed to load function {0} from module {1}'.format(name, module), problem_mark=name.mark) return None if not callable(func): echoerr(context='Error while checking segments (key {key})'.format(key=context.key), context_mark=name.mark, problem='imported “function” {0} from module {1} is not callable'.format(name, module), problem_mark=module.mark) return None return func
def check_func(self, value, context_mark, data, context, echoerr, func, msg_func): '''Check value using given function :param function func: Callable that should accept four positional parameters: #. checked value, #. ``data`` parameter with arbitrary data (supplied by top-level caller), #. current context and #. function used for echoing errors. This callable should return three values: #. determines whether ``check_func`` caller should proceed calling other checks, #. determines whether ``check_func`` should echo error on its own (it should be set to False if ``func`` echoes error itself) and #. determines whether function has found some errors in the checked value. :param function msg_func: Callable that takes checked value as the only positional parameter and returns a string that describes the problem. Only useful for small checker functions since it is ignored when second returned value is false. :return: proceed, hadproblem. ''' havemarks(value) proceed, echo, hadproblem = func(value, data, context, echoerr) if echo and hadproblem: echoerr(context=self.cmsg.format(key=context.key), context_mark=context_mark, problem=msg_func(value), problem_mark=value.mark) return proceed, hadproblem
def check_segment_data_key(key, data, context, echoerr): havemarks(key) has_module_name = '.' in key found = False for ext, theme in list_themes(data, context): for segments in theme.get('segments', {}).values(): for segment in segments: if 'name' in segment: if key == segment['name']: found = True break else: function_name = segment.get('function') if function_name: module, function_name = get_function_strings(function_name, ((None, theme),), ext) if has_module_name: full_name = module + '.' + function_name if key == full_name: found = True break else: if key == function_name: found = True break if found: break if found: break else: if data['theme_type'] != 'top': echoerr(context='Error while checking segment data', problem='found key {0} that cannot be associated with any segment'.format(key), problem_mark=key.mark) return True, False, True return True, False, False
def hl_exists(hl_group, data, context, echoerr, allow_gradients=False): havemarks(hl_group) ext = data['ext'] if ext not in data['colorscheme_configs']: # No colorschemes. Error was already reported, no need to report it # twice return [] r = [] for colorscheme, cconfig in data['colorscheme_configs'][ext].items(): if hl_group not in cconfig.get('groups', {}): r.append(colorscheme) elif not allow_gradients or allow_gradients == 'force': group_config = cconfig['groups'][hl_group] havemarks(group_config) hadgradient = False for ckey in ('fg', 'bg'): color = group_config.get(ckey) if not color: # No color. Error was already reported. continue havemarks(color) # Gradients are only allowed for function segments. Note that # whether *either* color or gradient exists should have been # already checked hascolor = color in data['colors_config'].get('colors', {}) hasgradient = color in data['colors_config'].get( 'gradients', {}) if hasgradient: hadgradient = True if allow_gradients is False and not hascolor and hasgradient: echoerr( context= 'Error while checking highlight group in theme (key {key})' .format(key=context.key), context_mark=hl_group.mark, problem= 'group {0} is using gradient {1} instead of a color'. format(hl_group, color), problem_mark=color.mark) r.append(colorscheme) continue if allow_gradients == 'force' and not hadgradient: echoerr( context= 'Error while checking highlight group in theme (key {key})' .format(key=context.key), context_mark=hl_group.mark, problem= 'group {0} should have at least one gradient color, but it has no' .format(hl_group), problem_mark=group_config.mark) r.append(colorscheme) return r
def hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr): havemarks(hl_group, cconfig) if hl_group not in cconfig.get('groups', {}): return False elif not allow_gradients or allow_gradients == 'force': group_config = cconfig['groups'][hl_group] while isinstance(group_config, unicode): try: group_config = cconfig['groups'][group_config] except KeyError: # No such group. Error was already reported when checking # colorschemes. return True havemarks(group_config) hadgradient = False for ckey in ('fg', 'bg'): color = group_config.get(ckey) if not color: # No color. Error was already reported when checking # colorschemes. return True havemarks(color) # Gradients are only allowed for function segments. Note that # whether *either* color or gradient exists should have been # already checked hascolor = color in data['colors_config'].get('colors', {}) hasgradient = color in data['colors_config'].get('gradients', {}) if hasgradient: hadgradient = True if allow_gradients is False and not hascolor and hasgradient: echoerr( context= 'Error while checking highlight group in theme (key {key})' .format(key=context.key), context_mark=hl_group.mark, problem='group {0} is using gradient {1} instead of a color' .format(hl_group, color), problem_mark=color.mark) return False if allow_gradients == 'force' and not hadgradient: echoerr( context= 'Error while checking highlight group in theme (key {key})'. format(key=context.key), context_mark=hl_group.mark, problem= 'group {0} should have at least one gradient color, but it has no' .format(hl_group), problem_mark=group_config.mark) return False return True
def hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr): havemarks(hl_group, cconfig) if hl_group not in cconfig.get('groups', {}): return False elif not allow_gradients or allow_gradients == 'force': group_config = cconfig['groups'][hl_group] while isinstance(group_config, unicode): try: group_config = cconfig['groups'][group_config] except KeyError: # No such group. Error was already reported when checking # colorschemes. return True havemarks(group_config) hadgradient = False for ckey in ('fg', 'bg'): color = group_config.get(ckey) if not color: # No color. Error was already reported when checking # colorschemes. return True havemarks(color) # Gradients are only allowed for function segments. Note that # whether *either* color or gradient exists should have been # already checked hascolor = color in data['colors_config'].get('colors', {}) hasgradient = color in data['colors_config'].get('gradients', {}) if hasgradient: hadgradient = True if allow_gradients is False and not hascolor and hasgradient: echoerr( context='Error while checking highlight group in theme (key {key})'.format( key=context.key), context_mark=hl_group.mark, problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color), problem_mark=color.mark ) return False if allow_gradients == 'force' and not hadgradient: echoerr( context='Error while checking highlight group in theme (key {key})'.format( key=context.key), context_mark=hl_group.mark, problem='group {0} should have at least one gradient color, but it has no'.format(hl_group), problem_mark=group_config.mark ) return False return True
def hl_exists(hl_group, data, context, echoerr, allow_gradients=False): havemarks(hl_group) ext = data['ext'] if ext not in data['colorscheme_configs']: # No colorschemes. Error was already reported, no need to report it # twice return [] r = [] for colorscheme, cconfig in data['colorscheme_configs'][ext].items(): if hl_group not in cconfig.get('groups', {}): r.append(colorscheme) elif not allow_gradients or allow_gradients == 'force': group_config = cconfig['groups'][hl_group] havemarks(group_config) hadgradient = False for ckey in ('fg', 'bg'): color = group_config.get(ckey) if not color: # No color. Error was already reported. continue havemarks(color) # Gradients are only allowed for function segments. Note that # whether *either* color or gradient exists should have been # already checked hascolor = color in data['colors_config'].get('colors', {}) hasgradient = color in data['colors_config'].get('gradients', {}) if hasgradient: hadgradient = True if allow_gradients is False and not hascolor and hasgradient: echoerr( context='Error while checking highlight group in theme (key {key})'.format( key=context.key), context_mark=hl_group.mark, problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color), problem_mark=color.mark ) r.append(colorscheme) continue if allow_gradients == 'force' and not hadgradient: echoerr( context='Error while checking highlight group in theme (key {key})'.format( key=context.key), context_mark=hl_group.mark, problem='group {0} should have at least one gradient color, but it has no'.format(hl_group), problem_mark=group_config.mark ) r.append(colorscheme) return r
def match(self, value, context_mark=None, data=None, context=(), echoerr=echoerr): '''Check that given value matches this specification :return: proceed, hadproblem. ''' havemarks(value) proceed, hadproblem = self.match_checks(value, context_mark, data, context, echoerr) if proceed: if self.keys or self.uspecs: for key, vali in self.keys.items(): valspec = self.specs[vali] if key in value: proceed, mhadproblem = valspec.match( value[key], value.mark, data, context.enter_key(value, key), echoerr ) if mhadproblem: hadproblem = True if not proceed: return False, hadproblem else: if not valspec.isoptional: hadproblem = True echoerr(context=self.cmsg.format(key=context.key), context_mark=None, problem='required key is missing: {0}'.format(key), problem_mark=value.mark) for key in value.keys(): havemarks(key) if key not in self.keys: for keyfunc, vali in self.uspecs: valspec = self.specs[vali] if isinstance(keyfunc, int): spec = self.specs[keyfunc] proceed, khadproblem = spec.match(key, context_mark, data, context, echoerr) else: proceed, khadproblem = keyfunc(key, data, context, echoerr) if khadproblem: hadproblem = True if proceed: proceed, vhadproblem = valspec.match( value[key], value.mark, data, context.enter_key(value, key), echoerr ) if vhadproblem: hadproblem = True break else: hadproblem = True if self.ufailmsg: echoerr(context=self.cmsg.format(key=context.key), context_mark=None, problem=self.ufailmsg(key), problem_mark=key.mark) return True, hadproblem
def check_group(group, data, context, echoerr): havemarks(group) if not isinstance(group, unicode): return True, False, False colorscheme = data['colorscheme'] ext = data['ext'] configs = [] if ext: if colorscheme == '__main__': configs.append([ config for config in data['ext_colorscheme_configs'][ext].items() ]) configs.append( [config for config in data['top_colorscheme_configs'].items()]) else: try: configs.append( [data['ext_colorscheme_configs'][ext][colorscheme]]) except KeyError: pass try: configs.append( [data['ext_colorscheme_configs'][ext]['__main__']]) except KeyError: pass try: configs.append([data['top_colorscheme_configs'][colorscheme]]) except KeyError: pass else: try: configs.append([data['top_colorscheme_configs'][colorscheme]]) except KeyError: pass new_echoerr = DelayedEchoErr(echoerr) hadproblem = False for config_lst in configs: tofind = len(config_lst) not_found = [] for config in config_lst: if isinstance(config, tuple): new_colorscheme, config = config new_data = data.copy() new_data['colorscheme'] = new_colorscheme else: new_data = data havemarks(config) try: group_data = config['groups'][group] except KeyError: not_found.append(config.mark.name) else: proceed, echo, chadproblem = check_group( group_data, new_data, context, echoerr, ) if chadproblem: hadproblem = True else: tofind -= 1 if not tofind: return proceed, echo, hadproblem if not proceed: break if not_found: new_echoerr( context= 'Error while checking group definition in colorscheme (key {key})' .format(key=context.key), problem='name {0} is not present in {1} {2} colorschemes: {3}'. format(group, tofind, ext, ', '.join(not_found)), problem_mark=group.mark) new_echoerr.echo_all() return True, False, hadproblem
def check_group(group, data, context, echoerr): havemarks(group) if not isinstance(group, unicode): return True, False, False colorscheme = data['colorscheme'] ext = data['ext'] configs = None if ext: def listed_key(d, k): try: return [d[k]] except KeyError: return [] if colorscheme == '__main__': colorscheme_names = set(data['ext_colorscheme_configs'][ext]) colorscheme_names.update(data['top_colorscheme_configs']) colorscheme_names.discard('__main__') configs = [ ( name, listed_key(data['ext_colorscheme_configs'][ext], name) + listed_key(data['ext_colorscheme_configs'][ext], '__main__') + listed_key(data['top_colorscheme_configs'], name) ) for name in colorscheme_names ] else: configs = [ ( colorscheme, listed_key(data['ext_colorscheme_configs'][ext], colorscheme) + listed_key(data['ext_colorscheme_configs'][ext], '__main__') + listed_key(data['top_colorscheme_configs'], colorscheme) ) ] else: try: configs = [(colorscheme, [data['top_colorscheme_configs'][colorscheme]])] except KeyError: pass hadproblem = False for new_colorscheme, config_lst in configs: not_found = [] new_data = data.copy() new_data['colorscheme'] = new_colorscheme for config in config_lst: havemarks(config) try: group_data = config['groups'][group] except KeyError: not_found.append(config.mark.name) else: proceed, echo, chadproblem = check_group( group_data, new_data, context, echoerr, ) if chadproblem: hadproblem = True if not proceed: break if not_found and len(not_found) == len(config_lst): echoerr( context='Error while checking group definition in colorscheme (key {key})'.format( key=context.key), problem='name {0} is not present anywhere in {1} {2} {3} colorschemes: {4}'.format( group, len(not_found), ext, new_colorscheme, ', '.join(not_found)), problem_mark=group.mark ) hadproblem = True return True, False, hadproblem
def check_segment_function(function_name, data, context, echoerr): havemarks(function_name) ext = data['ext'] module, function_name = get_function_strings(function_name, context, ext) if context[-2][1].get('type', 'function') == 'function': func = import_segment(function_name, data, context, echoerr, module=module) if not func: return True, False, True hl_groups = [] divider_hl_group = None if func.__doc__: H_G_USED_STR = 'Highlight groups used: ' LHGUS = len(H_G_USED_STR) D_H_G_USED_STR = 'Divider highlight group used: ' LDHGUS = len(D_H_G_USED_STR) pointer = 0 mark_name = '<{0} docstring>'.format(function_name) for i, line in enumerate(func.__doc__.split('\n')): if H_G_USED_STR in line: idx = line.index(H_G_USED_STR) + LHGUS hl_groups.append(( line[idx:], (mark_name, i + 1, idx + 1, func.__doc__), pointer + idx )) elif D_H_G_USED_STR in line: idx = line.index(D_H_G_USED_STR) + LDHGUS + 2 mark = Mark(mark_name, i + 1, idx + 1, func.__doc__, pointer + idx) divider_hl_group = MarkedUnicode(line[idx:-3], mark) pointer += len(line) + len('\n') hadproblem = False if divider_hl_group: r = hl_exists(divider_hl_group, data, context, echoerr, allow_gradients=True) if r: echoerr( context='Error while checking theme (key {key})'.format(key=context.key), context_mark=function_name.mark, problem=( 'found highlight group {0} not defined in the following colorschemes: {1}\n' '(Group name was obtained from function documentation.)' ).format(divider_hl_group, list_sep.join(r)), problem_mark=divider_hl_group.mark, ) hadproblem = True if check_hl_group_name(divider_hl_group, function_name.mark, context, echoerr): hadproblem = True if hl_groups: greg = re.compile(r'``([^`]+)``( \(gradient\))?') parsed_hl_groups = [] for line, mark_args, pointer in hl_groups: for s in line.split(', '): required_pack = [] sub_pointer = pointer for subs in s.split(' or '): match = greg.match(subs) try: if not match: continue hl_group = MarkedUnicode( match.group(1), Mark(*mark_args, pointer=sub_pointer + match.start(1)) ) if check_hl_group_name(hl_group, function_name.mark, context, echoerr): hadproblem = True gradient = bool(match.group(2)) required_pack.append((hl_group, gradient)) finally: sub_pointer += len(subs) + len(' or ') parsed_hl_groups.append(required_pack) pointer += len(s) + len(', ') del hl_group, gradient for required_pack in parsed_hl_groups: rs = [ hl_exists(hl_group, data, context, echoerr, allow_gradients=('force' if gradient else False)) for hl_group, gradient in required_pack ] if all(rs): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem=( 'found highlight groups list ({0}) with all groups not defined in some colorschemes\n' '(Group names were taken from function documentation.)' ).format(list_sep.join((h[0] for h in required_pack))), problem_mark=function_name.mark ) for r, h in zip(rs, required_pack): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( h[0], list_sep.join(r)) ) hadproblem = True else: r = hl_exists(function_name, data, context, echoerr, allow_gradients=True) if r: echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem=( 'found highlight group {0} not defined in the following colorschemes: {1}\n' '(If not specified otherwise in documentation, ' 'highlight group for function segments\n' 'is the same as the function name.)' ).format(function_name, list_sep.join(r)), problem_mark=function_name.mark ) hadproblem = True return True, False, hadproblem elif context[-2][1].get('type') != 'segment_list': if function_name not in context[0][1].get('segment_data', {}): main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None) if data['theme'] == main_theme_name: main_theme = {} else: main_theme = data['ext_theme_configs'].get(main_theme_name, {}) if ( function_name not in main_theme.get('segment_data', {}) and function_name not in data['ext_theme_configs'].get('__main__', {}).get('segment_data', {}) and not any(((function_name in theme.get('segment_data', {})) for theme in data['top_themes'].values())) ): echoerr(context='Error while checking segments (key {key})'.format(key=context.key), problem='found useless use of name key (such name is not present in theme/segment_data)', problem_mark=function_name.mark) return True, False, False
def check_segment_function(function_name, data, context, echoerr): havemarks(function_name) ext = data['ext'] module, function_name = get_function_strings(function_name, context, ext) if context[-2][1].get('type', 'function') == 'function': func = import_segment(function_name, data, context, echoerr, module=module) if not func: return True, False, True hl_groups = [] divider_hl_group = None hadproblem = False if func.__doc__: NO_H_G_USED_STR = 'No highlight groups are used (literal segment).' H_G_USED_STR = 'Highlight groups used: ' LHGUS = len(H_G_USED_STR) D_H_G_USED_STR = 'Divider highlight group used: ' LDHGUS = len(D_H_G_USED_STR) pointer = 0 mark_name = '<{0} docstring>'.format(function_name) for i, line in enumerate(func.__doc__.split('\n')): if H_G_USED_STR in line: idx = line.index(H_G_USED_STR) + LHGUS if hl_groups is None: idx -= LHGUS mark = Mark(mark_name, i + 1, idx + 1, func.__doc__, pointer + idx) echoerr( context='Error while checking theme (key {key})'.format(key=context.key), context_mark=function_name.mark, problem=( 'found highlight group definition in addition to sentense stating that ' 'no highlight groups are used' ), problem_mark=mark, ) hadproblem = True continue hl_groups.append(( line[idx:], (mark_name, i + 1, idx + 1, func.__doc__), pointer + idx )) elif D_H_G_USED_STR in line: idx = line.index(D_H_G_USED_STR) + LDHGUS + 2 mark = Mark(mark_name, i + 1, idx + 1, func.__doc__, pointer + idx) divider_hl_group = MarkedUnicode(line[idx:-3], mark) elif NO_H_G_USED_STR in line: idx = line.index(NO_H_G_USED_STR) if hl_groups: mark = Mark(mark_name, i + 1, idx + 1, func.__doc__, pointer + idx) echoerr( context='Error while checking theme (key {key})'.format(key=context.key), context_mark=function_name.mark, problem=( 'found sentense stating that no highlight groups are used ' 'in addition to highlight group definition' ), problem_mark=mark, ) hadproblem = True continue hl_groups = None pointer += len(line) + len('\n') if divider_hl_group: r = hl_exists(divider_hl_group, data, context, echoerr, allow_gradients=True) if r: echoerr( context='Error while checking theme (key {key})'.format(key=context.key), context_mark=function_name.mark, problem=( 'found highlight group {0} not defined in the following colorschemes: {1}\n' '(Group name was obtained from function documentation.)' ).format(divider_hl_group, list_sep.join(r)), problem_mark=divider_hl_group.mark, ) hadproblem = True if check_hl_group_name(divider_hl_group, function_name.mark, context, echoerr): hadproblem = True if hl_groups: greg = re.compile(r'``([^`]+)``( \(gradient\))?') parsed_hl_groups = [] for line, mark_args, pointer in hl_groups: for s in line.split(', '): required_pack = [] sub_pointer = pointer for subs in s.split(' or '): match = greg.match(subs) try: if not match: continue hl_group = MarkedUnicode( match.group(1), Mark(*mark_args, pointer=sub_pointer + match.start(1)) ) if check_hl_group_name(hl_group, function_name.mark, context, echoerr): hadproblem = True gradient = bool(match.group(2)) required_pack.append((hl_group, gradient)) finally: sub_pointer += len(subs) + len(' or ') parsed_hl_groups.append(required_pack) pointer += len(s) + len(', ') del hl_group, gradient for required_pack in parsed_hl_groups: rs = [ hl_exists(hl_group, data, context, echoerr, allow_gradients=('force' if gradient else False)) for hl_group, gradient in required_pack ] if all(rs): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem=( 'found highlight groups list ({0}) with all groups not defined in some colorschemes\n' '(Group names were taken from function documentation.)' ).format(list_sep.join((h[0] for h in required_pack))), problem_mark=function_name.mark ) for r, h in zip(rs, required_pack): echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( h[0], list_sep.join(r)) ) hadproblem = True elif hl_groups is not None: r = hl_exists(function_name, data, context, echoerr, allow_gradients=True) if r: echoerr( context='Error while checking theme (key {key})'.format(key=context.key), problem=( 'found highlight group {0} not defined in the following colorschemes: {1}\n' '(If not specified otherwise in documentation, ' 'highlight group for function segments\n' 'is the same as the function name.)' ).format(function_name, list_sep.join(r)), problem_mark=function_name.mark ) hadproblem = True return True, False, hadproblem elif context[-2][1].get('type') != 'segment_list': if function_name not in context[0][1].get('segment_data', {}): main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None) if data['theme'] == main_theme_name: main_theme = {} else: main_theme = data['ext_theme_configs'].get(main_theme_name, {}) if ( function_name not in main_theme.get('segment_data', {}) and function_name not in data['ext_theme_configs'].get('__main__', {}).get('segment_data', {}) and not any(((function_name in theme.get('segment_data', {})) for theme in data['top_themes'].values())) ): echoerr(context='Error while checking segments (key {key})'.format(key=context.key), problem='found useless use of name key (such name is not present in theme/segment_data)', problem_mark=function_name.mark) return True, False, False
def check_group(group, data, context, echoerr): havemarks(group) if not isinstance(group, unicode): return True, False, False colorscheme = data['colorscheme'] ext = data['ext'] configs = [] if ext: if colorscheme == '__main__': configs.append([config for config in data['ext_colorscheme_configs'][ext].items()]) configs.append([config for config in data['top_colorscheme_configs'].items()]) else: try: configs.append([data['ext_colorscheme_configs'][ext][colorscheme]]) except KeyError: pass try: configs.append([data['ext_colorscheme_configs'][ext]['__main__']]) except KeyError: pass try: configs.append([data['top_colorscheme_configs'][colorscheme]]) except KeyError: pass else: try: configs.append([data['top_colorscheme_configs'][colorscheme]]) except KeyError: pass new_echoerr = DelayedEchoErr(echoerr) hadproblem = False for config_lst in configs: tofind = len(config_lst) not_found = [] for config in config_lst: if isinstance(config, tuple): new_colorscheme, config = config new_data = data.copy() new_data['colorscheme'] = new_colorscheme else: new_data = data havemarks(config) try: group_data = config['groups'][group] except KeyError: not_found.append(config.mark.name) else: proceed, echo, chadproblem = check_group( group_data, new_data, context, echoerr, ) if chadproblem: hadproblem = True else: tofind -= 1 if not tofind: return proceed, echo, hadproblem if not proceed: break if not_found: new_echoerr( context='Error while checking group definition in colorscheme (key {key})'.format( key=context.key), problem='name {0} is not present in {1} {2} colorschemes: {3}'.format( group, tofind, ext, ', '.join(not_found)), problem_mark=group.mark ) new_echoerr.echo_all() return True, False, hadproblem