Difference between revisions of "GEPS 014: Plugin registration and management"

From Gramps
Jump to: navigation, search
(New page: GEP 14 plugin registration and management This GEP aims to introduce plugin registration and management in GRAMPS. P === Present situation=== What happens in version...)
 
m
 
(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
GEP 14  plugin registration and management
+
{{GEPS-Finished}}
 +
{{man menu|''' This GEP is now included in Gramps 3.2.x'''}}
  
 
This GEP aims to introduce plugin registration and management in GRAMPS.  
 
This GEP aims to introduce plugin registration and management in GRAMPS.  
[[Category:GEPS|P]]
 
  
 
=== Present situation===
 
=== Present situation===
Line 8: Line 8:
  
 
Disadvantages:
 
Disadvantages:
 
 
* loading plugins takes up a large part of the startup time of GRAMPS. This is especially annoying for CLI mode
 
* loading plugins takes up a large part of the startup time of GRAMPS. This is especially annoying for CLI mode
 
* all plugins are loaded, so all imports happen, in essence almost the entirity of GRAMPS is imported. When doing a CLI report, this eg means GTK is loaded, ...  
 
* all plugins are loaded, so all imports happen, in essence almost the entirity of GRAMPS is imported. When doing a CLI report, this eg means GTK is loaded, ...  
Line 14: Line 13:
 
* no management possible of what plugins should be loaded and enabled.
 
* no management possible of what plugins should be loaded and enabled.
 
* no way to catch duplicate plugins
 
* no way to catch duplicate plugins
 
  
 
===Proposal===
 
===Proposal===
 
This GEP proposes to change this to the following setup
 
This GEP proposes to change this to the following setup
# every plugin is accompanied by a plugin.gpr file, which is a gramps plugin register file. This contains an xml file with:
+
# every plugin is accompanied by a plugin.gpr file, which is a gramps plugin register file. This contains an xml (?? see below) file with:
 
#* plugin name (internationalization ???)
 
#* plugin name (internationalization ???)
 
#* plugin python file
 
#* plugin python file
 
#* plugin description
 
#* plugin description
 
#* optional plugin screenshots
 
#* optional plugin screenshots
 +
#* plugin mode (CLI, GUI, CLI_GUI)
 
#* plugin author + email
 
#* plugin author + email
 
#* plugin version
 
#* plugin version
Line 29: Line 28:
 
# some plugins types can be preloaded in the GUI mode, eg export/import ??
 
# some plugins types can be preloaded in the GUI mode, eg export/import ??
 
# when the user selects a plugin, the pluginmanager imports the plugin and returns the specific class
 
# when the user selects a plugin, the pluginmanager imports the plugin and returns the specific class
# There is a plugin manager interface showing all possible plugins, and an option to enable/disable. Some plugins are ptotected, meaning they cannot be disabled. For debugging, there is a load option importing a selected plugin again. If load fails, the traceback is available here too.
+
# There is a plugin manager interface showing all possible plugins, and an option to enable/disable. Some plugins are protected, meaning they cannot be disabled. For debugging, there is a load option importing a selected plugin again. If load fails, the traceback is available here too.
 
# A newly downloaded plugin must be enabled to make it available. In the case of name clash, the INSTALLDIR version takes precedence.
 
# A newly downloaded plugin must be enabled to make it available. In the case of name clash, the INSTALLDIR version takes precedence.
 +
 +
====Advantages====
 +
* it is possible to split between CLI and GUI code also in the plugins
 +
* one can disable plugins one does not want so as to simplify the plugin menu
 +
* added security (??)
 +
* duplicates are handled in a known way
 +
* easier support. The effective determination of the plugin classes will be done in one place, instead of a register method in every plugin.
  
 
===The gpr xml file ??===
 
===The gpr xml file ??===
Line 48: Line 54:
 
  PLUGINLIST = [DESCREPORT]
 
  PLUGINLIST = [DESCREPORT]
 
:This would simplify a lot things over an xml file.
 
:This would simplify a lot things over an xml file.
 +
 +
====Reply of HippySurfer====
 +
I think that the plugin description is better done in Python rather than XML.
 +
 +
We could use something like the following to read and load the plugin descriptions:
 +
First a class that represents a plugin:
 +
 +
<pre>
 +
class PlugIn(object):
 +
 +
  _version = None
 +
  _name = None
 +
 +
  def _set_version(self,version):
 +
      self._version = version
 +
 +
  def _get_version(self):
 +
      return self._version
 +
 +
  def _set_name(self,name):
 +
      self._name = name
 +
 +
  def _get_name(self):
 +
      return self._name
 +
 +
  version = property(_get_version,_set_version)
 +
  name = property(_get_name,_set_name)
 +
</pre>
 +
 +
Then walk the tree looking for plugin registration files and for each one that we find:
 +
 +
<pre>
 +
from gettext import gettext as _
 +
 +
plug = PlugIn()
 +
 +
execfile('test.py',{'_':_,
 +
                  'set_version':plug._set_version,
 +
                  'set_name':plug._set_name},
 +
        {})
 +
</pre>
 +
 +
The plugin registration file can then just be a Python file that has assess to the methods that are exported from the plugin object, e.g.:
 +
 +
<pre>
 +
test.py:
 +
set_version (2)
 +
set_name(_('my name'))
 +
</pre>
 +
 +
After the execfile you can access the values that have been set:
 +
 +
print plug.version
 +
print plug.name
 +
 +
There is no security here, the plugin registration code can still do what ever it likes but I don't see that as an issue. The plugins will not be run in a sandbox so why worry about their registration code.
 +
 +
Translation is simple because we can export '_'.
 +
 +
The functions that we choose to export could do anything we like, for
 +
instance you could export a function that would allow the plugin
 +
registration to query which version of gramps is running and register a
 +
different class. You could not do that if the registration was XML.
  
 
===Remark===
 
===Remark===
 
The reason to drive this GEP now is to enable cleanly plugin views. In this setup, the views of GRAMPS become plugins that can be enabled and disabled. Some views must always be present, so a way to not make plugins disabled must be present. The point is not to load views in the case CLI mode is done.
 
The reason to drive this GEP now is to enable cleanly plugin views. In this setup, the views of GRAMPS become plugins that can be enabled and disabled. Some views must always be present, so a way to not make plugins disabled must be present. The point is not to load views in the case CLI mode is done.
  
Views should also accomodate for more than one instance of the view. This must be worked out if this should be part of the pluginmanager or in some other configuration dialog.
+
Views should also accommodate for more than one instance of the view. This must be worked out if this should be part of the pluginmanager or in some other configuration dialog.
 +
 
 +
===Screenshots===
 +
 
 +
[[Image:Registered plugins.png|400px|thumb|left|Registered_plugins]]
 +
[[Image:Loaded plugins.png|400px|thumb|left|Loaded plugins]]
 +
[[Image:Plugins hidden.png|400px|thumb|left|Hidden plugins]]
 +
[[Image:Plugins detailed info.png|400px|thumb|left|Detailed information]]
 +
[[Image:Registered plugins edition.png|400px|thumb|left|Plugin edition]]
 +
[[Image:Registered plugins fr.png|400px|thumb|left|Registered plugins (localized)]]
 +
{{-}}
 +
===See Also===
 +
* Developer documentation: Create a Gramps Plugin Registration [<code>.gpr.py</code>] file:
 +
** [https://www.gramps-project.org/wiki/index.php?title=Addons_development&oldid=21401#Create_a_Gramps_Plugin_Registration_file per GEPS014 for Gramps 3.2 ] - Jan 2010
 +
** [[Addons_development#Create_a_Gramps_Plugin_Registration_file|for Gramps {{man version}}]] - Nov 2022 (major revision discussed for 5.2 version)
 +
[[Category:GEPS|P]]

Latest revision as of 22:47, 9 May 2023

Gnome-important.png
GEPS Closed

This GEPS (Gramps Enhancement Proposal) is closed and available in the version of Gramps indicated below.
Do not edit this page. Submit bugs/features to https://gramps-project.org/bugs/.

This GEP is now included in Gramps 3.2.x

This GEP aims to introduce plugin registration and management in GRAMPS.

Present situation

What happens in version 3.1: The pluginmanager runs through the directory INSTALLDIR/plugins, and GRAMPSDIR/plugins, loading all .py files. If these have a plugin register method then the textreport, gramplet, exportmethod, ... becomes available in GRAMPS.

Disadvantages:

  • loading plugins takes up a large part of the startup time of GRAMPS. This is especially annoying for CLI mode
  • all plugins are loaded, so all imports happen, in essence almost the entirity of GRAMPS is imported. When doing a CLI report, this eg means GTK is loaded, ...
  • from a security point of view, just importing everything from a directory is not ideal. However, as the user downloaded a plugin, he will probably run it no matter what.
  • no management possible of what plugins should be loaded and enabled.
  • no way to catch duplicate plugins

Proposal

This GEP proposes to change this to the following setup

  1. every plugin is accompanied by a plugin.gpr file, which is a gramps plugin register file. This contains an xml (?? see below) file with:
    • plugin name (internationalization ???)
    • plugin python file
    • plugin description
    • optional plugin screenshots
    • plugin mode (CLI, GUI, CLI_GUI)
    • plugin author + email
    • plugin version
    • plugin status (alpha, beta, final)
  2. on load of GRAMPS these files are parsed and the pluginmanager so has a list of plugins that are available. The GRAMPS ini or a new ini file lists all plugins that should be enabled by default in GRAMPS. Only those are visible in the plugin menu. A command line option allows to preload some plugins.
  3. some plugins types can be preloaded in the GUI mode, eg export/import ??
  4. when the user selects a plugin, the pluginmanager imports the plugin and returns the specific class
  5. There is a plugin manager interface showing all possible plugins, and an option to enable/disable. Some plugins are protected, meaning they cannot be disabled. For debugging, there is a load option importing a selected plugin again. If load fails, the traceback is available here too.
  6. A newly downloaded plugin must be enabled to make it available. In the case of name clash, the INSTALLDIR version takes precedence.

Advantages

  • it is possible to split between CLI and GUI code also in the plugins
  • one can disable plugins one does not want so as to simplify the plugin menu
  • added security (??)
  • duplicates are handled in a known way
  • easier support. The effective determination of the plugin classes will be done in one place, instead of a register method in every plugin.

The gpr xml file ??

A good definition for the xml must be present. Things to answer:

  • can we have gettext extract the name and description from the xml to create internationalization? Or should we have a setup like:
<name>
<default>Descendant Report</default>
<lang value='nl'>Afstammelings rapport</lang
</name>
  • what must be present in the xml file?
  • it would be easier if the gpr file is just an python file. Can this be done safely? Is it possible to require a python file with only a gettext import, and only a definition of a dict with the required defenitions. So something like:
from descreport.gpr.py import PLUGINLIST
where the descreport.gpr.py file is something like:
DESCREPORT = {'name': _('Descendant Report'), ...}
PLUGINLIST = [DESCREPORT]
This would simplify a lot things over an xml file.

Reply of HippySurfer

I think that the plugin description is better done in Python rather than XML.

We could use something like the following to read and load the plugin descriptions: First a class that represents a plugin:

 class PlugIn(object):

   _version = None
   _name = None

   def _set_version(self,version):
       self._version = version

   def _get_version(self):
       return self._version

   def _set_name(self,name):
       self._name = name

   def _get_name(self):
       return self._name

   version = property(_get_version,_set_version)
   name = property(_get_name,_set_name)

Then walk the tree looking for plugin registration files and for each one that we find:

 from gettext import gettext as _

 plug = PlugIn()

 execfile('test.py',{'_':_,
                   'set_version':plug._set_version,
                   'set_name':plug._set_name},
        {})

The plugin registration file can then just be a Python file that has assess to the methods that are exported from the plugin object, e.g.:

test.py:
 set_version (2)
 set_name(_('my name'))

After the execfile you can access the values that have been set:

print plug.version
print plug.name

There is no security here, the plugin registration code can still do what ever it likes but I don't see that as an issue. The plugins will not be run in a sandbox so why worry about their registration code.

Translation is simple because we can export '_'.

The functions that we choose to export could do anything we like, for instance you could export a function that would allow the plugin registration to query which version of gramps is running and register a different class. You could not do that if the registration was XML.

Remark

The reason to drive this GEP now is to enable cleanly plugin views. In this setup, the views of GRAMPS become plugins that can be enabled and disabled. Some views must always be present, so a way to not make plugins disabled must be present. The point is not to load views in the case CLI mode is done.

Views should also accommodate for more than one instance of the view. This must be worked out if this should be part of the pluginmanager or in some other configuration dialog.

Screenshots

Registered_plugins
Loaded plugins
Hidden plugins
Detailed information
Plugin edition
Registered plugins (localized)


See Also