Spyder is a Python IDE that is itself written in Python. Plugins are created by putting a python file in spyder’s ‘spyderplugins/’ directory, which you probably can’t do if you’re using the installed version of Spyder: you’ll instead need the Spyder source code. Spyder’s home repository can be found at bitbucket (https://bitbucket.org/spyder-ide/spyderlib/overview), but we have cloned this repository with the intent of modifying it slightly to make it better suit the needs of our particular users; that source can be found at:
In both cases, you can run that source-code version of Spyder by running the ‘bootstrap.py’ python script located in the root directory of the checkout. NOTE: this script checks to make sure Spyder is not already running before executing! This means that you must exit your installed version of Spyder first.
If you want to use Spyder to edit Spyder plugins, you’re going to have to launch boostrap.py with the command-line option “–new-instance” to test your changes. Alternatively, you can use a different Python IDE (such as Eclipse), and launch it from there.
All plugins in Spyder must reside in the spyderplugins/ directory, and take the form ‘p_[pluginname].py’. Let’s take a look at the simplest plugin in the tellurium codebase: p_tellurium_reset.py This is the plugin whose sole purpose in life is to remove or hide any elements we deem would be too confusing to our users, and which renames the application. We can’t change the splash screen from a plugin, because the splash screen has already been displayed before any plugins get loaded. But we can do basically anything else we want.
For now, the one thing this plugin does can be found in the ‘register_plugin’ function:
def register_plugin(self): """Register plugin in Spyder's main window""" DEBUG = bool(os.environ.get('SPYDER_DEBUG', '')) title = "Tellurium (from Spyder %s; Python %s.%s)" % (__version__, sys.version_info, sys.version_info) if DEBUG: title += " [DEBUG MODE]" self.main.setWindowTitle(title) icon_name = 'Tellurium_light.ico' if self.main.light else 'Tellurium_filled_small.ico' # Resampling SVG icon only on non-Windows platforms (see Issue 1314): self.main.setWindowIcon(get_icon(icon_name, resample=os.name != 'nt')) self.main.add_dockwidget(self)
Here, the Spyder main window is referenced with ‘self.main’, and its functions ‘setWindowTitle’ and ‘setWindowIcon’ are used to re-skin the application to say “Tellurium’ at the top, and to use the Tellurium icon (which can be found in spyderplugins/images/) for the window. The ‘add_docwidget’ line is required for all plugins, as is defining (even as a stub) all of the other functions in this file. (As of this writing (February 2014), the plugin does not actually remove or hide anything else in the application, but may in the future.)
Other plugins are perhaps more instructive from an actually-doing-things perspective. The one I’ve used as a template a couple times is the ‘pylint’ plugin, a plugin that uses pylint to analyze Python code for errors, inefficiencies, and non-standard uses, and report the results. This plugin can be found at spyderplugins/p_pylint.py, and makes use of spyderplugins/widgets/pylintgui.py and spyderplugins/images/pylint.png. I won’t analyze the code here (as there is a lot I have yet to understand), but I found it very helpful when creating my own plugin: I basically started by copying the whole thing, removing things I didn’t need, and modifying the rest.
A test ‘hello world’ plugin based on the pylint module can be found in the current (2/2014) codebase, though obviously it will be removed for any actual release. It creates a window with a button you can click that will append ‘Hello, world!’ a changeable number of times to an editable text window. Its code can be found in spyderplugins/p_hello.py, and it uses spyderplugins/widgets/hellogui.py and spyderplugins/images/hello.png
The basic features of the plugin include:
A different ‘hello world’ plugin for Spyder can be found at http://eezitech.blogspot.fr/2013/09/python-spyder-ide-plugin-example.html. It takes a slightly different tack on what the plugin should do, but the basics are the same.