3292: register plugins, load on need, not on start of GRAMPS - GEPS 014

Improvements: gen.plug only depends on gen, relationship default is moved
to Relationship.py, and config for hidden to a gui.pluginmanager


svn: r13405
This commit is contained in:
Benny Malengier
2009-10-25 13:52:29 +00:00
parent c10da3fec5
commit d25cdc3958
28 changed files with 161 additions and 181 deletions

View File

@@ -30,14 +30,14 @@ from _pluginreg import (PluginData, PluginRegister, REPORT, TOOL,
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
CATEGORY_QR_PLACE, CATEGORY_QR_REPOSITORY, CATEGORY_QR_NOTE,
CATEGORY_QR_DATE, PTYPE_STR )
from _manager import PluginManager
from _manager import BasePluginManager
from _import import ImportPlugin
from _export import ExportPlugin
from _docgenplugin import DocGenPlugin
from utils import *
__all__ = [ "docbackend", "docgen", "menu", Plugin, PluginData,
PluginRegister, PluginManager,
PluginRegister, BasePluginManager,
ImportPlugin, ExportPlugin, DocGenPlugin,
REPORT, TOOL, CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
CATEGORY_WEB, CATEGORY_BOOK, CATEGORY_GRAPHVIZ,

View File

@@ -45,9 +45,7 @@ from gettext import gettext as _
#
#-------------------------------------------------------------------------
import gen.utils
import Relationship
from gen.plug import PluginRegister
import config
#-------------------------------------------------------------------------
#
@@ -58,30 +56,27 @@ _UNAVAILABLE = _("No description was provided")
#-------------------------------------------------------------------------
#
# PluginManager
# BasePluginManager
#
#-------------------------------------------------------------------------
class PluginManager(gen.utils.Callback):
""" PluginManager is a Singleton which manages plugins """
class BasePluginManager(object):
""" unique singleton storage class for a PluginManager. """
__instance = None
__signals__ = { 'plugins-reloaded' : None }
def get_instance():
""" Use this function to get the instance of the PluginManager """
if PluginManager.__instance is None:
PluginManager.__instance = 1 # Set to 1 for __init__()
PluginManager.__instance = PluginManager()
return PluginManager.__instance
if BasePluginManager.__instance is None:
BasePluginManager.__instance = 1 # Set to 1 for __init__()
BasePluginManager.__instance = BasePluginManager()
return BasePluginManager.__instance
get_instance = staticmethod(get_instance)
def __init__(self):
""" This function should only be run once by get_instance() """
if PluginManager.__instance is not 1:
if BasePluginManager.__instance is not 1:
raise Exception("This class is a singleton. "
"Use the get_instance() method")
gen.utils.Callback.__init__(self)
self.__import_plugins = []
self.__export_plugins = []
@@ -91,28 +86,12 @@ class PluginManager(gen.utils.Callback):
self.__failmsg_list = []
self.__external_opt_dict = {}
self.__success_list = []
self.__relcalc_class = Relationship.RelationshipCalculator
self.__mod2text = {}
self.__pgr = PluginRegister.get_instance()
self.__registereddir_set = set()
self.__loaded_plugins = {}
self.__hidden_plugins = set([])
for id in config.get('plugin.hiddenplugins'):
self.__hidden_plugins.add(id)
self.__hidden_changed()
def __hidden_changed(self, *args):
#if hidden changed, stored data must be emptied as it could contain
#something that now must be hidden
self.__import_plugins = []
self.__export_plugins = []
self.__docgen_plugins = []
#objects that need to know if the plugins available changed, are
#listening to this signal to update themselves. If a plugin becomes
#(un)hidden, this should happen, so we emit.
self.emit('plugins-reloaded')
def reg_plugins(self, direct):
"""
@@ -133,16 +112,7 @@ class PluginManager(gen.utils.Callback):
# registereddir_list list for use on reloading.
self.__registereddir_set.add(dirpath)
self.__pgr.scan_dir(dirpath)
# set correct relationship calculator based on LANG
for plugin in self.__pgr.relcalc_plugins():
if os.environ["LANG"] in plugin.lang_list:
#the loaded module is put in variable mod
mod = self.load_plugin(plugin)
if mod:
self.__relcalc_class = eval('mod.' +
plugin.relcalcclass)
break
# load plugins that request to be loaded on startup
for plugin in self.__pgr.filter_load_on_reg():
mod = self.load_plugin(plugin)
@@ -167,6 +137,15 @@ class PluginManager(gen.utils.Callback):
self.__failmsg_list.append((filename, sys.exc_info()))
return None
def empty_managed_plugins(self):
""" For some plugins, managed Plugin are used. These are only
reobtained from the registry if this method is called
"""
# TODO: do other lists need to be reset here, too?
self.__import_plugins = []
self.__export_plugins = []
self.__docgen_plugins = []
def reload_plugins(self):
""" Reload previously loaded plugins """
pymod = re.compile(r"^(.*)\.py$")
@@ -175,10 +154,7 @@ class PluginManager(gen.utils.Callback):
self.__failmsg_list = []
# attempt to reload all plugins that have succeeded in the past
# TODO: do other lists need to be reset here, too?
self.__import_plugins[:] = []
self.__export_plugins[:] = []
self.__docgen_plugins[:] = []
self.empty_managed_plugins()
for plugin in self.__success_list:
filename = plugin[0]
@@ -211,35 +187,6 @@ class PluginManager(gen.utils.Callback):
except:
self.__failmsg_list.append((filename, sys.exc_info()))
self.emit('plugins-reloaded')
def get_hidden_plugin_ids(self):
"""
Returns copy of the set hidden plugin ids
"""
return self.__hidden_plugins.copy()
def hide_plugin(self, id):
""" Hide plugin with given id. This will hide the plugin so queries do
not return it anymore, and write this change to the config.
Note that config will then emit a signal
"""
self.__hidden_plugins.add(id)
hideset = [x for x in self.__hidden_plugins]
config.set('plugin.hiddenplugins', hideset)
config.save()
self.__hidden_changed()
def unhide_plugin(self, id):
""" Unhide plugin with given id. This will unhide the plugin so queries
return it again, and write this change to the config
"""
self.__hidden_plugins.remove(id)
hideset = [x for x in self.__hidden_plugins]
config.set('plugin.hiddenplugins', hideset)
config.save()
self.__hidden_changed()
def get_fail_list(self):
""" Return the list of failed plugins. """
return self.__failmsg_list
@@ -249,38 +196,33 @@ class PluginManager(gen.utils.Callback):
return self.__success_list
def get_reg_reports(self, gui=True):
""" Return list of non hidden registered reports
""" Return list of registered reports
:Param gui: bool indicating if GUI reports or CLI reports must be
returned
"""
return [plg for plg in self.__pgr.report_plugins(gui) if plg.id not in
self.__hidden_plugins]
return self.__pgr.report_plugins(gui)
def get_reg_tools(self, gui=True):
""" Return list of non hidden registered tools
""" Return list of registered tools
:Param gui: bool indicating if GUI reports or CLI reports must be
returned
"""
return [plg for plg in self.__pgr.tool_plugins(gui) if plg.id not in
self.__hidden_plugins]
return self.__pgr.tool_plugins(gui)
def get_reg_quick_reports(self):
""" Return list of non hidden registered quick reports
""" Return list of registered quick reports
"""
return [plg for plg in self.__pgr.quickreport_plugins() if plg.id not in
self.__hidden_plugins]
return self.__pgr.quickreport_plugins()
def get_reg_mapservices(self):
""" Return list of non hidden registered mapservices
""" Return list of registered mapservices
"""
return [plg for plg in self.__pgr.mapservice_plugins() if plg.id not in
self.__hidden_plugins]
return self.__pgr.mapservice_plugins()
def get_reg_bookitems(self):
""" Return list of non hidden reports registered as bookitem
""" Return list of reports registered as bookitem
"""
return [plg for plg in self.__pgr.bookitem_plugins() if plg.id not in
self.__hidden_plugins]
return self.__pgr.bookitem_plugins()
def get_external_opt_dict(self):
""" Return the dictionary of external options. """
@@ -290,6 +232,21 @@ class PluginManager(gen.utils.Callback):
""" Given a module name, return the module description. """
return self.__mod2text.get(module, '')
def get_reg_importers(self):
""" Return list of registered importers
"""
return self.__pgr.import_plugins()
def get_reg_exporters(self):
""" Return list of registered exporters
"""
return self.__pgr.export_plugins()
def get_reg_docgens(self):
""" Return list of registered docgen
"""
return self.__pgr.docgen_plugins()
def get_import_plugins(self):
"""
Get the list of import plugins.
@@ -300,9 +257,7 @@ class PluginManager(gen.utils.Callback):
## only PluginData, loading from module when importfunction needed?
if self.__import_plugins == []:
#The module still needs to be imported
imps = [pdata for pdata in self.__pgr.import_plugins() if pdata.id
not in self.__hidden_plugins]
for pdata in imps:
for pdata in self.get_reg_importers():
mod = self.load_plugin(pdata)
if mod:
imp = gen.plug.ImportPlugin(name=pdata.name,
@@ -323,9 +278,7 @@ class PluginManager(gen.utils.Callback):
## only PluginData, loading from module when export/options needed?
if self.__export_plugins == []:
#The modules still need to be imported
exps = [pdata for pdata in self.__pgr.export_plugins() if pdata.id
not in self.__hidden_plugins]
for pdata in exps:
for pdata in self.get_reg_exporters():
mod = self.load_plugin(pdata)
if mod:
exp = gen.plug.ExportPlugin(name=pdata.name,
@@ -349,9 +302,7 @@ class PluginManager(gen.utils.Callback):
## So, only do import when docgen.get_basedoc() is requested
if self.__docgen_plugins == []:
#The modules still need to be imported
dgdps = [pdata for pdata in self.__pgr.docgen_plugins() if pdata.id
not in self.__hidden_plugins]
for pdata in dgdps:
for pdata in self.get_reg_docgens():
mod = self.load_plugin(pdata)
if mod:
dgp = gen.plug.DocGenPlugin(name=pdata.name,
@@ -394,9 +345,3 @@ class PluginManager(gen.utils.Callback):
if item.get_module_name() not in failed_module_names ][:]
self.__docgen_plugins[:] = [ item for item in self.__docgen_plugins
if item.get_module_name() not in failed_module_names ][:]
def get_relationship_calculator(self):
"""
Return the relationship calculator for the current language.
"""
return self.__relcalc_class()