We've added the ability to use a variety of Python debuggers: pdb, PuDB, and PyCharm (professional version). Each has its pros and cons, but all are a significant improvement over self.debugLog()...
In the Plugins Preferences tab, there is a new Development section:
(bet you didn't even remember that tab was there). Because we need to start plugins in a special way for debugging to work, we need to show some special debugging menus. Check the checkbox to see those menus in each plugin's submenu. Next, each debugger needs to be started in a specific way, so select the debugger that you want to use.
By enabling debugging menus, each plugin will have some additional menu items on their submenu:
- Enable/Reload in Debugger
- Enable/Reload in Interactive Shell (discussed next)
Selecting the first will enable or restart the plugin with the plumbing enabled for the debugger you selected. We'll talk about the specifics for each next.
pdb
pdb is a command line debugger that's built-in to Python. We'll let you read the docs to find commands and features. What you do need to know is when you select Enable/Reload in Debugger, Indigo will restart your plugin and open a terminal window running pdb:
To add breakpoints to your code, you just add indigo.debugger() method calls where ever you want plugin execution to pause in the debugger. Trying to interactively add breakpoints from pdb or PuDB is hit-or-miss because of the threaded way in which Indigo plugins run. The most reliable to way to force a breakpoint is by manually adding the indigo.debugger() call to the python source and restarting the plugin. Also note indigo.debugger() calls are ignored (NOPs) when the plugin is not launched in debugger mode, so don't lose sleep over leaving an indigo.debugger() call in a shipping plugin.
PuDB
PuDB is a more graphical debugger, much like to the old Borland Turbo debugger from many years ago:
As with pdb, you add breakpoints to your code by adding indigo.debugger() method calls where ever you want plugin execution to pause in the debugger.
PyCharm
Finally, we were able to use PyCharm's remote debugging feature to enable plugin debugging. It requires a bit more setup, but if want to use a fantastic modern IDE, this is the choice for you. Note that because we're using the remote debugging feature, you can only use the professional version of PyCharm as the community edition doesn't support it.
With your plugin's project open in PyCharm, create a run configuration of type Remote Python Debug:
There are three important config parameters in this dialog (you can name the configuration anything you want). The first two tell how to connect: specify localhost in the Local host name box and 5678 in the Port field. The next field you need to adjust is the Path mappings field.
Recall that the recommended way of developing Indigo plugins is to put your plugin in a central location (not inside the Indigo folders), then make a symbolic link to it in the Plugins directory. We do this because the Indigo server moves a plugin between two different folders when enabling/disabling. An IDE/editor will get confused when this happens, so by putting the actual code in a place that never moves and allowing the Indigo Server to move a symbolic link around, you get around this issue.
Because of this, you need to tell PyCharm where the actual path to the source is when the plugin is enabled and being debugged. Click the ellipsis button at the end of the Path mappings field to add a mapping. On the Local path side, you want to specify the actual path to your plugin's source (i.e. /Users/you/path/to/myplugin.indigoPlugin). On the Remote path side, you want to specify the path to your plugin's symlink when the plugin is enabled (i.e. /Library/Application Support/Perceptive Automation/Indigo 7/Plugins/myplugin.indigoPlugin). Tip: to get the path to a file in the Finder, right click on the file to show the contextual menu, then press the Option key. The Copy item will change to Copy as Pathname which is exactly what you want.
One other option is the Suspend after connect checkbox: if you have that checked, then when your plugin restarts with the debugger, it will pause execution in the __init__ method. We don't recommend doing this since you can add breakpoints anywhere you want in the code, including in the __init__ method.
That's it for setup! To debug, just run the remote debug configuration and then restart your plugin in the debugger. Unlike when using pdb and PuDB, you don't need to add explicit breakpoints to the source code using indigo.debugger() – rather, just interactively add breakpoints in PyCharm:
You can step through code, inspect, etc., just like you are debugging any other Python project.
We hope that you'll find a great debugging solution for your needs in one of these options. We've added a couple of new API methods on the plugin objects that are part of this change:
- plugin.isRunning() – will return true if the plugin is enabled, initialized, and running
- plugin.restartAndDebug() – a parallel to the restart() method except that it starts the plugin running in the selected debugger
Plugin Specific Interactive Shell
Another great debugging tool is the ability to open a scripting shell that's specific to your plugin's context. This shell is like the more general shell you get when you select the Plugins->Open Scripting Shell menu item, except that because we launch it as part of your plugins startup, it has access to everything in your plugin. You can call methods that your plugin implements, inspect your plugin's objects, etc.