From acd55bbd87817a4e5e00e3bbdb13109a8787e79a Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 26 Aug 2014 19:25:32 +0400 Subject: [PATCH] Handle errors from Renderer._set_highlighting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is done by moving appropriate get_highlighting calls into segment.py: here errors from contents_func are handled as well. This is a “fix” for #480 that will make such failures cause segment to disappear with better header which should show segment which caused the error. Closes #480 --- powerline/__init__.py | 7 ++--- powerline/renderer.py | 26 +----------------- powerline/segment.py | 61 ++++++++++++++++++++++++++++++++++--------- powerline/theme.py | 12 ++++++++- 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/powerline/__init__.py b/powerline/__init__.py index 529826ab..4f5f32bc 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -467,7 +467,7 @@ class Powerline(object): self.get_module_attr = gen_module_attr_getter(self.pl, self.import_paths, self.imported_modules) - self.renderer_options.update( + mergedicts(self.renderer_options, dict( pl=self.pl, term_truecolor=self.common_config['term_truecolor'], ambiwidth=self.common_config['ambiwidth'], @@ -480,7 +480,7 @@ class Powerline(object): 'shutdown_event': self.shutdown_event, 'get_module_attr': self.get_module_attr, }, - ) + )) if not self.run_once and self.common_config['reload_config']: interval = self.common_config['interval'] @@ -535,7 +535,8 @@ class Powerline(object): self._purge_configs('colorscheme') if load_colorscheme: self.colorscheme_config = self.load_colorscheme_config(self.ext_config['colorscheme']) - self.renderer_options['colorscheme'] = Colorscheme(self.colorscheme_config, self.colors_config) + self.renderer_options['theme_kwargs']['colorscheme'] = ( + Colorscheme(self.colorscheme_config, self.colors_config)) if load_theme: self._purge_configs('theme') diff --git a/powerline/renderer.py b/powerline/renderer.py index b4a3e9a6..2a80528d 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -36,8 +36,6 @@ class Renderer(object): base class only records this parameter to a ``.local_themes`` attribute. :param dict theme_kwargs: Keyword arguments for ``Theme`` class constructor. - :param Colorscheme colorscheme: - Colorscheme object that holds colors configuration. :param PowerlineLogger pl: Object used for logging. :param int ambiwidth: @@ -93,7 +91,6 @@ class Renderer(object): theme_config, local_themes, theme_kwargs, - colorscheme, pl, ambiwidth=1, **options): @@ -107,7 +104,6 @@ class Renderer(object): self.theme = Theme(theme_config=theme_config, **theme_kwargs) self.local_themes = local_themes self.theme_kwargs = theme_kwargs - self.colorscheme = colorscheme self.width_data = { 'N': 1, # Neutral 'Na': 1, # Narrow @@ -150,21 +146,6 @@ class Renderer(object): ''' self.theme.shutdown() - def _set_highlighting(self, segment): - segment['highlight'] = self.colorscheme.get_highlighting( - segment['highlight_group'], - segment['mode'], - segment.get('gradient_level') - ) - if segment['divider_highlight_group']: - segment['divider_highlight'] = self.colorscheme.get_highlighting( - segment['divider_highlight_group'], - segment['mode'] - ) - else: - segment['divider_highlight'] = None - return segment - def get_segment_info(self, segment_info, mode): '''Get segment information. @@ -264,12 +245,7 @@ class Renderer(object): def do_render(self, mode, width, side, line, output_raw, output_width, segment_info, theme): '''Like Renderer.render(), but accept theme in place of matcher_info ''' - segments = [ - self._set_highlighting(segment) - for segment in ( - theme.get_segments(side, line, self.get_segment_info(segment_info, mode), mode) - ) - ] + segments = list(theme.get_segments(side, line, self.get_segment_info(segment_info, mode), mode)) current_width = 0 diff --git a/powerline/segment.py b/powerline/segment.py index d282a765..15659d71 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -99,7 +99,8 @@ def get_attr_func(contents_func, key, args): return lambda pl, shutdown_event: func(pl=pl, shutdown_event=shutdown_event, **args) -def process_segment_lister(pl, segment_info, parsed_segments, side, mode, lister, subsegments, patcher_args): +def process_segment_lister(pl, segment_info, parsed_segments, side, mode, colorscheme, + lister, subsegments, patcher_args): for subsegment_info, subsegment_update in lister(pl=pl, segment_info=segment_info, **patcher_args): draw_inner_divider = subsegment_update.pop('draw_inner_divider', False) old_pslen = len(parsed_segments) @@ -120,7 +121,15 @@ def process_segment_lister(pl, segment_info, parsed_segments, side, mode, lister ): continue - process_segment(pl, side, subsegment_info, parsed_segments, subsegment, subsegment_mode or mode) + process_segment( + pl, + side, + subsegment_info, + parsed_segments, + subsegment, + subsegment_mode or mode, + colorscheme, + ) new_pslen = len(parsed_segments) if new_pslen > old_pslen + 1 and draw_inner_divider is not None: for i in range(old_pslen, new_pslen - 1) if side == 'left' else range(old_pslen + 1, new_pslen): @@ -128,16 +137,37 @@ def process_segment_lister(pl, segment_info, parsed_segments, side, mode, lister return None -def process_segment(pl, side, segment_info, parsed_segments, segment, mode): +def set_segment_highlighting(pl, colorscheme, segment): + try: + segment['highlight'] = colorscheme.get_highlighting( + segment['highlight_group'], + segment['mode'], + segment.get('gradient_level') + ) + if segment['divider_highlight_group']: + segment['divider_highlight'] = colorscheme.get_highlighting( + segment['divider_highlight_group'], + segment['mode'] + ) + else: + segment['divider_highlight'] = None + except Exception as e: + pl.exception('Failed to set highlight group: {0}', str(e)) + return False + else: + return True + + +def process_segment(pl, side, segment_info, parsed_segments, segment, mode, colorscheme): segment = segment.copy() segment['mode'] = mode + pl.prefix = segment['name'] if segment['type'] in ('function', 'segment_list'): - pl.prefix = segment['name'] try: if segment['type'] == 'function': contents = segment['contents_func'](pl, segment_info) else: - contents = segment['contents_func'](pl, segment_info, parsed_segments, side, mode) + contents = segment['contents_func'](pl, segment_info, parsed_segments, side, mode, colorscheme) except Exception as e: pl.exception('Exception while computing segment: {0}', str(e)) return @@ -176,12 +206,15 @@ def process_segment(pl, side, segment_info, parsed_segments, segment, mode): if draw_inner_divider is not None: segment_copy['draw_soft_divider'] = draw_inner_divider draw_inner_divider = segment_copy.pop('draw_inner_divider', None) - append(segment_copy) + if set_segment_highlighting(pl, colorscheme, segment_copy): + append(segment_copy) else: segment['contents'] = contents - parsed_segments.append(segment) + if set_segment_highlighting(pl, colorscheme, segment): + parsed_segments.append(segment) elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None): - parsed_segments.append(segment) + if set_segment_highlighting(pl, colorscheme, segment): + parsed_segments.append(segment) def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, get_module_attr, top_theme): @@ -239,11 +272,13 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge 'divider_highlight_group': None, 'before': None, 'after': None, - 'contents_func': lambda pl, segment_info, parsed_segments, side, mode: process_segment_lister( - pl, segment_info, parsed_segments, side, mode, - patcher_args=args, - subsegments=subsegments, - lister=_contents_func, + 'contents_func': lambda pl, segment_info, parsed_segments, side, mode, colorscheme: ( + process_segment_lister( + pl, segment_info, parsed_segments, side, mode, colorscheme, + patcher_args=args, + subsegments=subsegments, + lister=_contents_func, + ) ), 'contents': None, 'priority': None, diff --git a/powerline/theme.py b/powerline/theme.py index 2c15886d..3bf8483b 100644 --- a/powerline/theme.py +++ b/powerline/theme.py @@ -31,9 +31,11 @@ class Theme(object): pl, get_module_attr, top_theme, + colorscheme, main_theme_config=None, run_once=False, shutdown_event=None): + self.colorscheme = colorscheme self.dividers = theme_config['dividers'] self.dividers = dict(( (key, dict((k, u(v)) @@ -116,7 +118,15 @@ class Theme(object): if mode not in segment['exclude_modes'] and ( not segment['include_modes'] or mode in segment['include_modes'] ): - process_segment(self.pl, side, segment_info, parsed_segments, segment, mode) + process_segment( + self.pl, + side, + segment_info, + parsed_segments, + segment, + mode, + self.colorscheme, + ) for segment in parsed_segments: segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after'] # Align segment contents