From 94354475b5d259d012e4d8eab8c270938dbcadf6 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 15 Apr 2013 23:49:04 +0400 Subject: [PATCH] Add support for full powerline reloading at runtime Is not guaranteed to work in all cases. --- powerline/__init__.py | 58 +++++++++++++++++++++---- powerline/bindings/ipython/post_0_11.py | 4 +- powerline/bindings/ipython/pre_0_11.py | 4 +- powerline/ipython.py | 4 +- powerline/shell.py | 4 +- powerline/vim.py | 4 +- 6 files changed, 59 insertions(+), 19 deletions(-) diff --git a/powerline/__init__.py b/powerline/__init__.py index a6958ba9..716c8abf 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -336,14 +336,22 @@ class Powerline(object): Instance of the class that manages (re)loading of the configuration. ''' - def __init__(self, - ext, - renderer_module=None, - run_once=False, - logger=None, - use_daemon_threads=True, - shutdown_event=None, - config_loader=None): + def __init__(self, *args, **kwargs): + self.init_args = (args, kwargs) + self.init(*args, **kwargs) + + def init(self, + ext, + renderer_module=None, + run_once=False, + logger=None, + use_daemon_threads=True, + shutdown_event=None, + config_loader=None): + '''Do actual initialization. + + __init__ function only stores the arguments. + ''' self.ext = ext self.run_once = run_once self.logger = logger @@ -732,10 +740,42 @@ class Powerline(object): def setup(self, *args, **kwargs): '''Setup the environment to use powerline. - To be overridden by subclasses, this one only saves args and kwargs. + To be overridden by subclasses, this one only saves args and kwargs and + unsets shutdown_event. ''' + self.shutdown_event.clear() self.setup_args = (args, kwargs) + def reload(self): + '''Reload powerline after update. + + Should handle most (but not all) powerline updates. + + Purges out all powerline modules and modules imported by powerline for + segment and matcher functions. Requires defining ``setup`` function that + updates reference to main powerline object. + + .. warning:: + Not guaranteed to work properly, use it at your own risk. It + may break your python code. + ''' + from imp import reload + modules = self.imported_modules | set((module for module in sys.modules if module.startswith('powerline'))) + modules_holder = [] + for module in modules: + try: + # Needs to hold module to prevent garbage collecting until they + # are all reloaded. + modules_holder.append(sys.modules.pop(module)) + except KeyError: + pass + PowerlineClass = getattr(__import__(self.__module__, fromlist=(self.__class__.__name__,)), self.__class__.__name__) + self.shutdown(set_event=True) + init_args, init_kwargs = self.init_args + powerline = PowerlineClass(*init_args, **init_kwargs) + setup_args, setup_kwargs = self.setup_args + powerline.setup(*setup_args, **setup_kwargs) + def shutdown(self, set_event=True): '''Shut down all background threads. diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py index 12aa8ef0..e30d8797 100644 --- a/powerline/bindings/ipython/post_0_11.py +++ b/powerline/bindings/ipython/post_0_11.py @@ -43,12 +43,12 @@ class PowerlinePromptManager(PromptManager): class ConfigurableIpythonPowerline(IpythonPowerline): - def __init__(self, ip, is_prompt, old_widths): + def init(self, ip, is_prompt, old_widths): config = ip.config.Powerline self.config_overrides = config.get('config_overrides') self.theme_overrides = config.get('theme_overrides', {}) self.paths = config.get('paths') - super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths) + super(ConfigurableIpythonPowerline, self).init(is_prompt, old_widths) old_prompt_manager = None diff --git a/powerline/bindings/ipython/pre_0_11.py b/powerline/bindings/ipython/pre_0_11.py index 68fb34f1..e740c8f3 100644 --- a/powerline/bindings/ipython/pre_0_11.py +++ b/powerline/bindings/ipython/pre_0_11.py @@ -86,11 +86,11 @@ class PowerlinePrompt2(PowerlinePromptOut): class ConfigurableIpythonPowerline(IpythonPowerline): - def __init__(self, is_prompt, old_widths, config_overrides=None, theme_overrides={}, paths=None): + def init(self, is_prompt, old_widths, config_overrides=None, theme_overrides={}, paths=None): self.config_overrides = config_overrides self.theme_overrides = theme_overrides self.paths = paths - super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths) + super(ConfigurableIpythonPowerline, self).init(is_prompt, old_widths) def setup(**kwargs): diff --git a/powerline/ipython.py b/powerline/ipython.py index 29c165b1..7d675058 100644 --- a/powerline/ipython.py +++ b/powerline/ipython.py @@ -23,8 +23,8 @@ class RewriteResult(object): class IpythonPowerline(Powerline): - def __init__(self, is_prompt, old_widths): - super(IpythonPowerline, self).__init__( + def init(self, is_prompt, old_widths): + super(IpythonPowerline, self).init( 'ipython', renderer_module=('.prompt' if is_prompt else None), use_daemon_threads=True diff --git a/powerline/shell.py b/powerline/shell.py index b2fea9e7..cbd55fae 100644 --- a/powerline/shell.py +++ b/powerline/shell.py @@ -14,10 +14,10 @@ def mergeargs(argvalue): class ShellPowerline(Powerline): - def __init__(self, args, **kwargs): + def init(self, args, **kwargs): self.args = args self.theme_option = args.theme_option - super(ShellPowerline, self).__init__(args.ext[0], args.renderer_module, **kwargs) + super(ShellPowerline, self).init(args.ext[0], args.renderer_module, **kwargs) def load_main_config(self): r = super(ShellPowerline, self).load_main_config() diff --git a/powerline/vim.py b/powerline/vim.py index 3a0f7c8b..3594a6c0 100644 --- a/powerline/vim.py +++ b/powerline/vim.py @@ -23,8 +23,8 @@ def _override_from(config, override_varname): class VimPowerline(Powerline): - def __init__(self, pyeval='PowerlinePyeval', **kwargs): - super(VimPowerline, self).__init__('vim', **kwargs) + def init(self, pyeval='PowerlinePyeval', **kwargs): + super(VimPowerline, self).init('vim', **kwargs) self.last_window_id = 1 self.pyeval = pyeval self.window_statusline = '%!' + pyeval + '(\'powerline.statusline({0})\')'