Philipp Hörist pushed to branch master at gajim / gajim
Commits:
49bfc1f2 by Markus Wintermann at 2018-04-28T13:31:19+02:00
Add support for dynamic reloading of plugins
‎* rename the remove_plugin function to uninstall_plugin because it
deletes files on the disc and uninstall is the label of the button which
triggers this function
* added a new remove_plugin function, which deactivates the plugin (if
needed), removes it from the list of managed plugins and deletes the
contents of sys.modules
- - - - -
2 changed files:
- gajim/plugins/gui.py
- gajim/plugins/pluginmanager.py
Changes:
=====================================
gajim/plugins/gui.py
=====================================
--- a/gajim/plugins/gui.py
+++ b/gajim/plugins/gui.py
@@ -252,7 +252,7 @@ class PluginsWindow(object):
if iter:
plugin = model.get_value(iter, Column.PLUGIN)
try:
- app.plugin_manager.remove_plugin(plugin)
+ app.plugin_manager.uninstall_plugin(plugin)
except PluginsystemError as e:
WarningDialog(_('Unable to properly remove the plugin'),
str(e), self.window)
=====================================
gajim/plugins/pluginmanager.py
=====================================
--- a/gajim/plugins/pluginmanager.py
+++ b/gajim/plugins/pluginmanager.py
@@ -150,6 +150,32 @@ class PluginManager(metaclass=Singleton):
plugin.version, plugin.__module__, plugin.short_name))
@log_calls('PluginManager')
+ def remove_plugin(self, plugin):
+ '''
+ removes the plugin from the plugin list and deletes all loaded modules
+ from sys. This way we will have a fresh start when the plugin gets added
+ agin.
+ '''
+ if plugin.active:
+ self.deactivate_plugin(plugin)
+
+ self.plugins.remove(plugin)
+
+ # remove modules from cache
+ base_package = plugin.__module__.split('.')[0]
+ # get the subpackages/-modules of the base_package. Add a dot to the
+ # name to avoid name problems (removing module_abc if base_package is
+ # module_ab)
+ modules_to_remove = [module for module in sys.modules
+ if module.startswith('{}.'.format(base_package))]
+ # remove the base_package itself
+ if base_package in sys.modules:
+ modules_to_remove.append(base_package)
+
+ for module_to_remove in modules_to_remove:
+ del sys.modules[module_to_remove]
+
+ @log_calls('PluginManager')
def add_plugins(self, plugin_classes):
for plugin_class in plugin_classes:
self.add_plugin(plugin_class)
@@ -532,20 +558,9 @@ class PluginManager(metaclass=Singleton):
continue
module = None
-
try:
- if module_name in sys.modules:
- if path == configpaths.get('PLUGINS_BASE'):
- # Only reload plugins from Gajim base dir when they
- # dont exist. This means plugins in the user path are
- # always preferred.
- continue
- from imp import reload
- log.info('Reloading %s', module_name)
- module = reload(sys.modules[module_name])
- else:
- log.info('Loading %s', module_name)
- module = __import__(module_name)
+ log.info('Loading %s', module_name)
+ module = __import__(module_name)
except Exception as error:
log.warning(
"While trying to load {plugin}, exception occurred".format(plugin=elem_name),
@@ -633,14 +648,14 @@ class PluginManager(metaclass=Singleton):
if len(dirs) > 1:
raise PluginsystemError(_('Archive is malformed'))
- base_dir, user_dir = configpaths.get('PLUGINS_DIRS')
+ user_dir = configpaths.get('PLUGINS_USER')
plugin_dir = os.path.join(user_dir, dirs[0])
if os.path.isdir(plugin_dir):
# Plugin dir already exists
if not owerwrite:
raise PluginsystemError(_('Plugin already exists'))
- self.remove_plugin(self.get_plugin_by_path(plugin_dir))
+ self.uninstall_plugin(self.get_plugin_by_path(plugin_dir))
zip_file.extractall(user_dir)
zip_file.close()
@@ -652,7 +667,7 @@ class PluginManager(metaclass=Singleton):
plugin = self.plugins[-1]
return plugin
- def remove_plugin(self, plugin):
+ def uninstall_plugin(self, plugin):
'''
Deactivate and remove plugin from `plugins` list
'''
@@ -665,15 +680,10 @@ class PluginManager(metaclass=Singleton):
raise PluginsystemError(error[1][1])
if plugin:
- if plugin.active:
- self.deactivate_plugin(plugin)
+ self.remove_plugin(plugin)
rmtree(plugin.__path__, False, on_error)
- self.plugins.remove(plugin)
if self._plugin_has_entry_in_global_config(plugin):
self._remove_plugin_entry_in_global_config(plugin)
- del sys.modules[plugin.__module__.split('.')[0]]
- del plugin.__module__.split('.')[-1]
- del plugin
def get_plugin_by_path(self, plugin_dir):
for plugin in self.plugins:
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/49bfc1f226e0b5e8fcceef5802140a9f2c…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/49bfc1f226e0b5e8fcceef5802140a9f2c…
You're receiving this email because of your account on dev.gajim.org.