Add support for reloading configuration in the main thread

This commit is contained in:
ZyX 2013-04-06 18:09:45 +04:00
parent 296107d68e
commit d1d05c9dcf
5 changed files with 59 additions and 32 deletions

View File

@ -168,7 +168,13 @@ Common configuration is a subdictionary that is a value of ``common`` key in
``interval``
Number, determines time (in seconds) between checks for changed
configuration. Use ``null`` to disable. Defaults to 10.
configuration. Checks are done in a seprate thread. Use ``null`` to check
for configuration changes on ``.render()`` call in main thread.
Defaults to ``None``.
``reload_config``
Boolean, determines whether configuration should be reloaded at all.
Defaults to ``True``.
Extension-specific configuration
--------------------------------

View File

@ -121,6 +121,7 @@ class Powerline(object):
}
self.shutdown_event = shutdown_event or Event()
self.config_loader = config_loader or ConfigLoader(shutdown_event=self.shutdown_event)
self.run_loader_update = False
self.renderer_options = {}
@ -191,9 +192,10 @@ class Powerline(object):
},
)
if not self.run_once:
interval = self.common_config.get('interval', 10)
if not self.run_once and self.common_config.get('reload_config', True):
interval = self.common_config.get('interval', None)
self.config_loader.set_interval(interval)
self.run_loader_update = (interval is None)
if interval is not None and not self.config_loader.is_alive():
self.config_loader.start()
@ -347,6 +349,8 @@ class Powerline(object):
def update_renderer(self):
'''Updates/creates a renderer if needed.'''
if self.run_loader_update:
self.config_loader.update()
create_renderer_kwargs = None
with self.cr_kwargs_lock:
if self.create_renderer_kwargs:

View File

@ -107,39 +107,41 @@ class ConfigLoader(MultiRunnedThread):
return self.loaded[path]
except KeyError:
r = self._load(path)
if self.interval is not None:
self.loaded[path] = r
self.loaded[path] = r
return r
def update(self):
toload = []
with self.lock:
for path, functions in self.watched.items():
for function in functions:
if self.watcher(path):
function(path)
toload.append(path)
with self.lock:
for key, functions in list(self.missing.items()):
remove = False
for condition_function, function in list(functions):
try:
path = condition_function(key)
except Exception as e:
self.exception('Error while running condition function for key {0}: {1}', key, str(e))
else:
if path:
toload.append(path)
function(path)
functions.remove((condition_function, function))
if not functions:
self.missing.pop(key)
for path in toload:
try:
self.loaded[path] = self._load(path)
except Exception as e:
self.exception('Error while loading {0}: {1}', path, str(e))
def run(self):
while self.interval is not None and not self.shutdown_event.is_set():
toload = []
with self.lock:
for path, functions in self.watched.items():
for function in functions:
if self.watcher(path):
function(path)
toload.append(path)
with self.lock:
for key, functions in list(self.missing.items()):
remove = False
for condition_function, function in list(functions):
try:
path = condition_function(key)
except Exception as e:
self.exception('Error while running condition function for key {0}: {1}', key, str(e))
else:
if path:
toload.append(path)
function(path)
functions.remove((condition_function, function))
if not functions:
self.missing.pop(key)
for path in toload:
try:
self.loaded[path] = self._load(path)
except Exception as e:
self.exception('Error while loading {0}: {1}', path, str(e))
self.update()
self.shutdown_event.wait(self.interval)
def exception(self, msg, *args, **kwargs):

View File

@ -419,6 +419,7 @@ main_spec = (Spec(
lambda value: 'unknown debugging level {0}'.format(value)).optional(),
log_format=Spec().type(str).optional(),
interval=Spec().either(Spec().cmp('gt', 0.0), Spec().type(type(None))).optional(),
reload_config=Spec().type(bool).optional(),
).context_message('Error while loading common configuration (key {key})'),
ext=Spec(
vim=Spec(

View File

@ -242,6 +242,20 @@ class TestConfigReload(TestCase):
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
def test_reload_theme_main(self):
with replace_item(globals(), 'config', deepcopy(config)):
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')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('themes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
replaces = {}