summaryrefslogtreecommitdiffstats
path: root/powerline/lint/checks.py
diff options
context:
space:
mode:
Diffstat (limited to 'powerline/lint/checks.py')
-rw-r--r--powerline/lint/checks.py866
1 files changed, 866 insertions, 0 deletions
diff --git a/powerline/lint/checks.py b/powerline/lint/checks.py
new file mode 100644
index 0000000..8d9cb12
--- /dev/null
+++ b/powerline/lint/checks.py
@@ -0,0 +1,866 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import re
+import logging
+
+from collections import defaultdict
+
+from powerline.lib.threaded import ThreadedSegment
+from powerline.lib.unicode import unicode
+from powerline.lint.markedjson.markedvalue import MarkedUnicode
+from powerline.lint.markedjson.error import DelayedEchoErr, Mark
+from powerline.lint.selfcheck import havemarks
+from powerline.lint.context import JStr, list_themes
+from powerline.lint.imp import WithPath, import_function, import_segment
+from powerline.lint.spec import Spec
+from powerline.lint.inspect import getconfigargspec
+
+
+list_sep = JStr(', ')
+
+
+generic_keys = set((
+ 'exclude_modes', 'include_modes',
+ 'exclude_function', 'include_function',
+ 'width', 'align',
+ 'name',
+ 'draw_soft_divider', 'draw_hard_divider',
+ 'priority',
+ 'after', 'before',
+ 'display'
+))
+type_keys = {
+ 'function': set(('function', 'args', 'draw_inner_divider')),
+ 'string': set(('contents', 'type', 'highlight_groups', 'divider_highlight_group')),
+ 'segment_list': set(('function', 'segments', 'args', 'type')),
+}
+required_keys = {
+ 'function': set(('function',)),
+ 'string': set(()),
+ 'segment_list': set(('function', 'segments',)),
+}
+highlight_keys = set(('highlight_groups', 'name'))
+
+
+def get_function_strings(function_name, context, ext):
+ if '.' in function_name:
+ module, function_name = function_name.rpartition('.')[::2]
+ else:
+ module = context[0][1].get(
+ 'default_module', MarkedUnicode('powerline.segments.' + ext, None))
+ return module, function_name
+
+
+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_config(d, theme, data, context, echoerr):
+ if len(context) == 4:
+ ext = context[-2][0]
+ else:
+ # local_themes
+ ext = context[-3][0]
+ if ext not in data['lists']['exts']:
+ echoerr(context='Error while loading {0} extension configuration'.format(ext),
+ context_mark=ext.mark,
+ problem='extension configuration does not exist')
+ return True, False, True
+ if (
+ (ext not in data['configs'][d] or theme not in data['configs'][d][ext])
+ and theme not in data['configs']['top_' + d]
+ ):
+ echoerr(context='Error while loading {0} from {1} extension configuration'.format(d[:-1], ext),
+ problem='failed to find configuration file {0}/{1}/{2}.json'.format(d, ext, theme),
+ problem_mark=theme.mark)
+ return True, False, True
+ return True, False, False
+
+
+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 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_translated_group_name(group, data, context, echoerr):
+ return check_group(group, data, context, echoerr)
+
+
+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_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 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 check_full_segment_data(segment, data, context, echoerr):
+ if 'name' not in segment and 'function' not in segment:
+ return True, False, False
+
+ ext = data['ext']
+ theme_segment_data = context[0][1].get('segment_data', {})
+ main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
+ if not main_theme_name or data['theme'] == main_theme_name:
+ top_segment_data = {}
+ else:
+ top_segment_data = data['ext_theme_configs'].get(main_theme_name, {}).get('segment_data', {})
+
+ if segment.get('type', 'function') == 'function':
+ function_name = segment.get('function')
+ if function_name:
+ module, function_name = get_function_strings(function_name, context, ext)
+ names = [module + '.' + function_name, function_name]
+ else:
+ names = []
+ elif segment.get('name'):
+ names = [segment['name']]
+ else:
+ return True, False, False
+
+ segment_copy = segment.copy()
+
+ for key in ('before', 'after', 'args', 'contents'):
+ if key not in segment_copy:
+ for segment_data in [theme_segment_data, top_segment_data]:
+ for name in names:
+ try:
+ val = segment_data[name][key]
+ k = segment_data[name].keydict[key]
+ segment_copy[k] = val
+ except KeyError:
+ pass
+
+ return check_key_compatibility(segment_copy, data, context, echoerr)
+
+
+highlight_group_spec = Spec().ident().copy
+_highlight_group_spec = highlight_group_spec().context_message(
+ 'Error while checking function documentation while checking theme (key {key})')
+
+
+def check_hl_group_name(hl_group, context_mark, context, echoerr):
+ '''Check highlight group name: it should match naming conventions
+
+ :param str hl_group:
+ Checked group.
+ :param Mark context_mark:
+ Context mark. May be ``None``.
+ :param Context context:
+ Current context.
+ :param func echoerr:
+ Function used for error reporting.
+
+ :return: ``False`` if check succeeded and ``True`` if it failed.
+ '''
+ return _highlight_group_spec.match(hl_group, context_mark=context_mark, context=context, echoerr=echoerr)[1]
+
+
+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 sentence 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 sentence 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 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 = []
+ 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_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_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_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
+
+
+threaded_args_specs = {
+ 'interval': Spec().cmp('gt', 0.0),
+ 'update_first': Spec().type(bool),
+ 'shutdown_event': Spec().error('Shutdown event must be set by powerline'),
+}
+
+
+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_args(get_functions, args, data, context, echoerr):
+ new_echoerr = DelayedEchoErr(echoerr)
+ count = 0
+ hadproblem = False
+ for func in get_functions(data, context, new_echoerr):
+ count += 1
+ shadproblem = check_args_variant(func, args, data, context, echoerr)
+ if shadproblem:
+ hadproblem = True
+
+ if not count:
+ hadproblem = True
+ if new_echoerr:
+ new_echoerr.echo_all()
+ else:
+ echoerr(context='Error while checking segment arguments (key {key})'.format(key=context.key),
+ context_mark=context[-2][1].mark,
+ problem='no suitable segments found')
+
+ return True, False, hadproblem
+
+
+def get_one_segment_function(data, context, echoerr):
+ ext = data['ext']
+ function_name = context[-2][1].get('function')
+ if function_name:
+ module, function_name = get_function_strings(function_name, context, ext)
+ func = import_segment(function_name, data, context, echoerr, module=module)
+ if func:
+ yield func
+
+
+common_names = defaultdict(set)
+
+
+def register_common_name(name, cmodule, cname):
+ s = cmodule + '.' + cname
+ cmodule_mark = Mark('<common name definition>', 1, 1, s, 1)
+ cname_mark = Mark('<common name definition>', 1, len(cmodule) + 1, s, len(cmodule) + 1)
+ common_names[name].add((MarkedUnicode(cmodule, cmodule_mark), MarkedUnicode(cname, cname_mark)))
+
+
+def get_all_possible_functions(data, context, echoerr):
+ name = context[-2][0]
+ module, name = name.rpartition('.')[::2]
+ if module:
+ func = import_segment(name, data, context, echoerr, module=module)
+ if func:
+ yield func
+ else:
+ if name in common_names:
+ for cmodule, cname in common_names[name]:
+ cfunc = import_segment(cname, data, context, echoerr, module=MarkedUnicode(cmodule, None))
+ if cfunc:
+ yield cfunc
+ for ext, theme_config in list_themes(data, context):
+ for segments in theme_config.get('segments', {}).values():
+ for segment in segments:
+ if segment.get('type', 'function') == 'function':
+ function_name = segment.get('function')
+ current_name = segment.get('name')
+ if function_name:
+ module, function_name = get_function_strings(function_name, ((None, theme_config),), ext)
+ if current_name == name or function_name == name:
+ func = import_segment(function_name, data, context, echoerr, module=module)
+ if func:
+ yield func
+
+
+def check_exinclude_function(name, data, context, echoerr):
+ ext = data['ext']
+ module, name = name.rpartition('.')[::2]
+ if not module:
+ module = MarkedUnicode('powerline.selectors.' + ext, None)
+ func = import_function('selector', name, data, context, echoerr, module=module)
+ if not func:
+ return True, False, True
+ return True, False, False
+
+
+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