Initial support for #770
What was done: - Implemented loading using configuration hierarhy as proposed in the issue - Implemented group aliasing What was not: - Some tests (config_reload) are failing - Other (test_configuration) are spamming console with unexpected messages - No support for powerline-lint - No tests for new functionality - Specifically I have not checked whether group aliasing actually works - Colorschemes were not ported Some other things: I have named this branch `config-ng` because I have other ideas about configuration and it would be good to include them making only one possibly backwards-incompatible merge commit instead of many. Specifically I am going to rebase `merge-config` branch here.
This commit is contained in:
parent
2d1a964e32
commit
97266b7ffc
|
@ -9,6 +9,7 @@ from powerline.colorscheme import Colorscheme
|
|||
from powerline.lib.config import ConfigLoader
|
||||
from powerline.lib.unicode import safe_unicode, FailedUnicode
|
||||
from powerline.config import DEFAULT_SYSTEM_CONFIG_DIR
|
||||
from powerline.lib import mergedicts
|
||||
|
||||
from threading import Lock, Event
|
||||
|
||||
|
@ -220,6 +221,22 @@ def finish_common_config(common_config):
|
|||
return common_config
|
||||
|
||||
|
||||
if sys.version_info < (3,):
|
||||
# `raise exception[0], None, exception[1]` is a SyntaxError in python-3*
|
||||
# Not using ('''…''') because this syntax does not work in python-2.6
|
||||
exec(('def reraise(exception):\n'
|
||||
' if type(exception) is tuple:\n'
|
||||
' raise exception[0], None, exception[1]\n'
|
||||
' else:\n'
|
||||
' raise exception\n'))
|
||||
else:
|
||||
def reraise(exception):
|
||||
if type(exception) is tuple:
|
||||
raise exception[0].with_traceback(exception[1])
|
||||
else:
|
||||
raise exception
|
||||
|
||||
|
||||
class Powerline(object):
|
||||
'''Main powerline class, entrance point for all powerline uses. Sets
|
||||
powerline up and loads the configuration.
|
||||
|
@ -455,7 +472,38 @@ class Powerline(object):
|
|||
|
||||
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
|
||||
'''
|
||||
return self._load_config(os.path.join('colorschemes', self.ext, name), 'colorscheme')
|
||||
# TODO Make sure no colorscheme name ends with __ (do it in
|
||||
# powerline-lint)
|
||||
levels = (
|
||||
os.path.join('colorschemes', name),
|
||||
os.path.join('colorschemes', self.ext, '__main__'),
|
||||
os.path.join('colorschemes', self.ext, name),
|
||||
)
|
||||
config = {}
|
||||
loaded = 0
|
||||
exceptions = []
|
||||
for cfg_path in levels:
|
||||
try:
|
||||
lvl_config = self._load_config(cfg_path, 'colorscheme')
|
||||
except IOError as e:
|
||||
if sys.version_info < (3,):
|
||||
tb = sys.exc_info()[2]
|
||||
exceptions.append((e, tb))
|
||||
else:
|
||||
exceptions.append(e)
|
||||
else:
|
||||
if not cfg_path.endswith('__'):
|
||||
loaded += 1
|
||||
mergedicts(config, lvl_config)
|
||||
if not loaded:
|
||||
for exception in exceptions:
|
||||
if type(exception) is tuple:
|
||||
e = exception[0]
|
||||
else:
|
||||
e = exception
|
||||
self.exception('Failed to load colorscheme: {0}', e, exception=exception)
|
||||
raise e
|
||||
return config
|
||||
|
||||
def load_colors_config(self):
|
||||
'''Get colorscheme.
|
||||
|
@ -562,5 +610,11 @@ class Powerline(object):
|
|||
def exception(self, msg, *args, **kwargs):
|
||||
if 'prefix' not in kwargs:
|
||||
kwargs['prefix'] = 'powerline'
|
||||
exception = kwargs.pop('exception', None)
|
||||
pl = getattr(self, 'pl', None) or get_fallback_logger()
|
||||
if exception:
|
||||
try:
|
||||
reraise(exception)
|
||||
except Exception:
|
||||
return pl.exception(msg, *args, **kwargs)
|
||||
return pl.exception(msg, *args, **kwargs)
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from copy import copy
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str
|
||||
|
||||
|
||||
DEFAULT_MODE_KEY = None
|
||||
|
@ -70,32 +74,41 @@ class Colorscheme(object):
|
|||
else:
|
||||
return self.colors[gradient]
|
||||
|
||||
def get_highlighting(self, groups, mode, gradient_level=None):
|
||||
trans = self.translations.get(mode, {})
|
||||
for group in hl_iter(groups):
|
||||
if 'groups' in trans and group in trans['groups']:
|
||||
def get_group_props(self, mode, trans, group, translate_colors=True):
|
||||
if isinstance(group, (str, unicode)):
|
||||
try:
|
||||
group_props = trans['groups'][group]
|
||||
except KeyError:
|
||||
try:
|
||||
group_props = trans['groups'][group]
|
||||
group_props = self.groups[group]
|
||||
except KeyError:
|
||||
continue
|
||||
break
|
||||
|
||||
return None
|
||||
else:
|
||||
return self.get_group_props(mode, trans, group_props, True)
|
||||
else:
|
||||
try:
|
||||
group_props = copy(self.groups[group])
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
return self.get_group_props(mode, trans, group_props, False)
|
||||
else:
|
||||
if translate_colors:
|
||||
group_props = copy(group)
|
||||
try:
|
||||
ctrans = trans['colors']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
for key in ('fg', 'bg'):
|
||||
try:
|
||||
group_props[key] = ctrans[group_props[key]]
|
||||
except KeyError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
return group_props
|
||||
else:
|
||||
return group
|
||||
|
||||
def get_highlighting(self, groups, mode, gradient_level=None):
|
||||
trans = self.translations.get(mode, {})
|
||||
for group in hl_iter(groups):
|
||||
group_props = self.get_group_props(mode, trans, group)
|
||||
if group_props:
|
||||
break
|
||||
else:
|
||||
raise KeyError('Highlighting groups not found in colorscheme: ' + ', '.join(hl_iter(groups)))
|
||||
|
|
|
@ -101,7 +101,7 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=True) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
config['config']['common']['spaces'] = 1
|
||||
add_watcher_events(p, 'config', wait=False, interval=0.05)
|
||||
# When running once thread should not start
|
||||
|
@ -117,7 +117,7 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=False) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['config']['common']['spaces'] = 1
|
||||
add_watcher_events(p, 'config')
|
||||
|
@ -141,14 +141,19 @@ class TestConfigReload(TestCase):
|
|||
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
|
||||
add_watcher_events(p, 'config')
|
||||
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colorschemes/test/nonexistent')
|
||||
self.assertAccessEvents('config', 'colorschemes/nonexistent', 'colorschemes/test/__main__', 'colorschemes/test/nonexistent')
|
||||
# It should normally handle file missing error
|
||||
self.assertEqual(p.logger._pop_msgs(), ['exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'])
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load colorscheme: colorschemes/nonexistent',
|
||||
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/__main__',
|
||||
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/nonexistent',
|
||||
'exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'
|
||||
])
|
||||
|
||||
config['config']['ext']['test']['colorscheme'] = '2'
|
||||
add_watcher_events(p, 'config')
|
||||
self.assertEqual(p.render(), '<2 3 1> s <3 4 False>>><1 4 4>g <4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colorschemes/test/2')
|
||||
self.assertAccessEvents('config', 'colorschemes/2', 'colorschemes/test/__main__', 'colorschemes/test/2')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
config['config']['ext']['test']['theme'] = '2'
|
||||
|
@ -170,7 +175,7 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=False) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
|
||||
add_watcher_events(p, 'config')
|
||||
|
@ -192,7 +197,7 @@ class TestConfigReload(TestCase):
|
|||
},
|
||||
}
|
||||
while not p._will_create_renderer():
|
||||
sleep(0.000001)
|
||||
sleep(0.1)
|
||||
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><2 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('colorschemes/test/nonexistentraise')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
@ -202,7 +207,7 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=False) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['colors']['colors']['col1'] = 5
|
||||
add_watcher_events(p, 'colors')
|
||||
|
@ -215,12 +220,12 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=False) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
|
||||
add_watcher_events(p, 'colorschemes/test/default')
|
||||
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('colorschemes/test/default')
|
||||
self.assertAccessEvents('colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
pop_events()
|
||||
|
||||
|
@ -228,7 +233,7 @@ class TestConfigReload(TestCase):
|
|||
with get_powerline(run_once=False) as p:
|
||||
with replace_item(globals(), 'config', deepcopy(config)):
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default')
|
||||
|
@ -242,7 +247,7 @@ class TestConfigReload(TestCase):
|
|||
config['config']['common']['interval'] = None
|
||||
with get_powerline(run_once=False) as p:
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
||||
|
@ -257,7 +262,7 @@ class TestConfigReload(TestCase):
|
|||
config['config']['common']['interval'] = None
|
||||
with get_powerline(run_once=True) as p:
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
||||
|
|
Loading…
Reference in New Issue