Replace various __import__ calls with one Powerline.get_module_attr
Also makes some more errors non-fatal: - Failure to import renderer class in case there is an existing renderer object - Failure to import segment function - Failure to import matcher function One of the purposes: create a function that is able to collect all imported modules to reload them (really purge out from `sys.modules` and let the python do its job when reimporting powerline and recreating Powerline and other objects).
This commit is contained in:
parent
c2c2d7efca
commit
446eb42ea8
|
@ -407,6 +407,9 @@ class Powerline(object):
|
||||||
'common_config': self.common_config,
|
'common_config': self.common_config,
|
||||||
'run_once': self.run_once,
|
'run_once': self.run_once,
|
||||||
'shutdown_event': self.shutdown_event,
|
'shutdown_event': self.shutdown_event,
|
||||||
|
# Note: creates implicit reference to self meaning
|
||||||
|
# reference cycle.
|
||||||
|
'get_module_attr': self.get_module_attr,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -468,11 +471,12 @@ class Powerline(object):
|
||||||
self.renderer_options['theme_config'] = self.load_theme_config(self.ext_config.get('theme', 'default'))
|
self.renderer_options['theme_config'] = self.load_theme_config(self.ext_config.get('theme', 'default'))
|
||||||
|
|
||||||
if create_renderer:
|
if create_renderer:
|
||||||
try:
|
Renderer = self.get_module_attr(self.renderer_module, 'renderer')
|
||||||
Renderer = __import__(self.renderer_module, fromlist=['renderer']).renderer
|
if not Renderer:
|
||||||
except Exception as e:
|
if hasattr(self, 'renderer'):
|
||||||
self.exception('Failed to import renderer module: {0}', str(e))
|
return
|
||||||
sys.exit(1)
|
else:
|
||||||
|
raise ImportError('Failed to obtain renderer')
|
||||||
|
|
||||||
# Renderer updates configuration file via segments’ .startup thus it
|
# Renderer updates configuration file via segments’ .startup thus it
|
||||||
# should be locked to prevent state when configuration was updated,
|
# should be locked to prevent state when configuration was updated,
|
||||||
|
@ -652,6 +656,34 @@ class Powerline(object):
|
||||||
with self.cr_kwargs_lock:
|
with self.cr_kwargs_lock:
|
||||||
self.cr_kwargs.clear()
|
self.cr_kwargs.clear()
|
||||||
|
|
||||||
|
def get_module_attr(self, module, attr, prefix='powerline'):
|
||||||
|
'''Import module and get its attribute.
|
||||||
|
|
||||||
|
Replaces ``from {module} import {attr}``.
|
||||||
|
|
||||||
|
:param str module:
|
||||||
|
Module name, will be passed as first argument to ``__import__``.
|
||||||
|
:param str attr:
|
||||||
|
Module attribute, will be passed to ``__import__`` as the only value
|
||||||
|
in ``fromlist`` tuple.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
Attribute value or ``None``. Note: there is no way to distinguish
|
||||||
|
between successfull import of attribute equal to ``None`` and
|
||||||
|
unsuccessfull import.
|
||||||
|
'''
|
||||||
|
oldpath = sys.path
|
||||||
|
sys.path = self.import_paths + sys.path
|
||||||
|
module = str(module)
|
||||||
|
attr = str(attr)
|
||||||
|
try:
|
||||||
|
return getattr(__import__(module, fromlist=(attr,)), attr)
|
||||||
|
except Exception as e:
|
||||||
|
self.pl.exception('Failed to import attr {0} from module {1}: {2}', attr, module, str(e), prefix=prefix)
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
sys.path = oldpath
|
||||||
|
|
||||||
def render(self, *args, **kwargs):
|
def render(self, *args, **kwargs):
|
||||||
'''Update/create renderer if needed and pass all arguments further to
|
'''Update/create renderer if needed and pass all arguments further to
|
||||||
``self.renderer.render()``.
|
``self.renderer.render()``.
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
# vim:fileencoding=utf-8:noet
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def gen_matcher_getter(ext, import_paths):
|
|
||||||
def get(match_name):
|
|
||||||
match_module, separator, match_function = match_name.rpartition('.')
|
|
||||||
if not separator:
|
|
||||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
|
||||||
match_function = match_name
|
|
||||||
oldpath = sys.path
|
|
||||||
sys.path = import_paths + sys.path
|
|
||||||
try:
|
|
||||||
return getattr(__import__(str(match_module), fromlist=[str(match_function)]), match_function)
|
|
||||||
finally:
|
|
||||||
sys.path = oldpath
|
|
||||||
return get
|
|
|
@ -55,14 +55,11 @@ def get_segment_key(merge, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def get_function(data, segment):
|
def get_function(data, segment):
|
||||||
oldpath = sys.path
|
|
||||||
sys.path = data['path'] + sys.path
|
|
||||||
segment_module = str(segment.get('module', data['default_module']))
|
segment_module = str(segment.get('module', data['default_module']))
|
||||||
name = str(segment['name'])
|
function = data['get_module_attr'](segment_module, segment['name'], prefix='segment_generator')
|
||||||
try:
|
if not function:
|
||||||
return None, getattr(__import__(segment_module, fromlist=[name]), name), segment_module
|
raise ImportError('Failed to obtain segment function')
|
||||||
finally:
|
return None, function, segment_module
|
||||||
sys.path = oldpath
|
|
||||||
|
|
||||||
|
|
||||||
def get_string(data, segment):
|
def get_string(data, segment):
|
||||||
|
@ -162,10 +159,10 @@ def process_segment(pl, side, segment_info, parsed_segments, segment):
|
||||||
parsed_segments.append(segment)
|
parsed_segments.append(segment)
|
||||||
|
|
||||||
|
|
||||||
def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=None):
|
def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, get_module_attr):
|
||||||
data = {
|
data = {
|
||||||
'default_module': default_module or 'powerline.segments.' + ext,
|
'default_module': default_module or 'powerline.segments.' + ext,
|
||||||
'path': common_config['paths'],
|
'get_module_attr': get_module_attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_key(merge, segment, module, key, default=None):
|
def get_key(merge, segment, module, key, default=None):
|
||||||
|
|
|
@ -29,6 +29,7 @@ class Theme(object):
|
||||||
theme_config,
|
theme_config,
|
||||||
common_config,
|
common_config,
|
||||||
pl,
|
pl,
|
||||||
|
get_module_attr,
|
||||||
main_theme_config=None,
|
main_theme_config=None,
|
||||||
run_once=False,
|
run_once=False,
|
||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
|
@ -53,7 +54,7 @@ class Theme(object):
|
||||||
theme_configs = [theme_config]
|
theme_configs = [theme_config]
|
||||||
if main_theme_config:
|
if main_theme_config:
|
||||||
theme_configs.append(main_theme_config)
|
theme_configs.append(main_theme_config)
|
||||||
get_segment = gen_segment_getter(pl, ext, common_config, theme_configs, theme_config.get('default_module'))
|
get_segment = gen_segment_getter(pl, ext, common_config, theme_configs, theme_config.get('default_module'), get_module_attr)
|
||||||
for segdict in itertools.chain((theme_config['segments'],),
|
for segdict in itertools.chain((theme_config['segments'],),
|
||||||
theme_config['segments'].get('above', ())):
|
theme_config['segments'].get('above', ())):
|
||||||
self.segments.append(new_empty_segment_line())
|
self.segments.append(new_empty_segment_line())
|
||||||
|
|
|
@ -6,7 +6,6 @@ import sys
|
||||||
from powerline.bindings.vim import vim_get_func, vim_getvar
|
from powerline.bindings.vim import vim_get_func, vim_getvar
|
||||||
from powerline import Powerline
|
from powerline import Powerline
|
||||||
from powerline.lib import mergedicts
|
from powerline.lib import mergedicts
|
||||||
from powerline.matcher import gen_matcher_getter
|
|
||||||
import vim
|
import vim
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
|
@ -80,18 +79,30 @@ class VimPowerline(Powerline):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_local_themes(self, local_themes):
|
def get_local_themes(self, local_themes):
|
||||||
self.get_matcher = gen_matcher_getter(self.ext, self.import_paths)
|
|
||||||
|
|
||||||
if not local_themes:
|
if not local_themes:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
return dict((
|
return dict((
|
||||||
(
|
(matcher, {'config': self.load_theme_config(val)})
|
||||||
(None if key == '__tabline__' else self.get_matcher(key)),
|
for matcher, key, val in (
|
||||||
{'config': self.load_theme_config(val)}
|
(
|
||||||
|
(None if k == '__tabline__' else self.get_matcher(k)),
|
||||||
|
k,
|
||||||
|
v
|
||||||
|
)
|
||||||
|
for k, v in local_themes.items()
|
||||||
|
) if (
|
||||||
|
matcher or
|
||||||
|
key == '__tabline__'
|
||||||
)
|
)
|
||||||
for key, val in local_themes.items())
|
))
|
||||||
)
|
|
||||||
|
def get_matcher(self, match_name):
|
||||||
|
match_module, separator, match_function = match_name.rpartition('.')
|
||||||
|
if not separator:
|
||||||
|
match_module = 'powerline.matchers.{0}'.format(self.ext)
|
||||||
|
match_function = match_name
|
||||||
|
return self.get_module_attr(match_module, match_function, prefix='matcher_generator')
|
||||||
|
|
||||||
def get_config_paths(self):
|
def get_config_paths(self):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue