Service Plugins
From Solipsis
This page contains a lot of informations for those wishing to create a new Service plugin. A nice way to discover services is to study the code. See, for instance, the basic chat plugin bundled with Solipsis.
| Table of contents |
What is a plugin ?
A service plugin is just a subdirectory inside the solipsis/services directory. The name of the subdirectory will also serve as the service ID, thus it must be chosen carefully:
- don't choose a name that was already chosen, or that is too generic
- don't choose a meaningless name
- use only //lowercase letters and underscores// ; any other character (including non-ascii characters) should be prohibited.
- don't change names once your service has been widely deployed
Examples of service names are: chat, filesharing, etc.
What do I put in the directory ?
Only one file is mandatory, it is the plugin.py file. It must define a class named Plugin that derives from the ServicePlugin class defined in solipsis/services/plugin.py. This class will have to define a certain number of methods that will be used by the navigator to grab information about your service and know how/when to invoke it.
It means your plugin.py will begin like this:
from solipsis.services.plugin import ServicePlugin class Plugin(ServicePlugin): [...]
For information about which methods should be overriden and why, see the embedded documentation in solipsis/services/plugin.py.
Recommended practices
Threads
The navigator has two threads:
- one is dedicated to the Graphical User Interface (GUI) and runs the wxPython event loop
- one is dedicated to network operations and runs the TwistedPython event loop
You always have to ensure that what you are doing is being done in the proper thread (not doing so is a sure recipe for strange crashes, buggy behaviour, data loss or whatever).
Practically, this means you'll use the proxy classes (UIProxy, TwistedProxy) defined in solipsis.util.uiproxy. These classes will transparently forward method calls to the proper thread. However, it will also make these method calls asynchronous: so if your method has to return a result, it can't do it directly but must call a callback (itself probably proxied) that will have been passed by the originating object.
Don't worry, it's actually simpler than what it sounds like. Most of the time, these asynchronous method calls are not a problem since the whole operation of a graphic and network app is itself event-driven.
Think about internationalization
Internationalization is done with gettext, which is the standard GNU tool for this. You'll use the _() function defined in solipsis.util.wxutils. You'll also likely use the build_po.sh script, which will automatically create a subdirectory for translations in your plugin directory - it will, by the way, initialize a French translation file.
Then, each translator will have to translate the relevant PO file, using an appropriate tool (there are many of these, e.g. poEdit (http://poedit.sourceforge.net/), gtranslator (http://gtranslator.sourceforge.net/), etc.). Finally, build_po.sh will have to be run again to compile PO files in their binary form.
In the end, your plugin directory will contain subdirectories named po/fr/LC_MESSAGES, po/de/LC_MESSAGES, etc. according to which languages your application has been translated into.
