MySQL Workbench Scripting and Plugin Development

5.2.26

Python Plugin Interface

Modules and Plugins

GRT Modules are a group of functions that are exported to be called from other parts of Workbench, such as Workbench itself, other modules, scripts and plugins in any of the languages supported. For a python function to be recognized as a plugin and be inserted into a context menu or to the Plugins menu,

The following example illustrates how to define a module and define a plugin in Python:

# import the wb module, where various utilities for working with plugins are defined
from wb import *

# import module for working with Workbench data structures
import grt

# create a module information descriptor. The variable name must be ModuleInfo
ModuleInfo = DefineModule(name= "MyModule", author= "My Name", version="1.0")


# export a function from this module, declaring its return and parameter types and then
# tell WB that it is a plugin to be shown in the Catalog submenu of the Plugins menu and takes the 
# catalog of the currently loaded model as input
@ModuleInfo.plugin("my.plugin.do_stuff", caption= "Do Stuff With Catalog", input= [wbinputs.currentCatalog()], pluginMenu= "Catalog")
@ModuleInfo.export(grt.INT, grt.classes.db_Catalog)
def do_stuff_with_catalog(catalog):
  # do stuff
  return 0

The Python plugin code must be in a file that ends with "_grt.py" and be placed in your users module folder for Workbench. You can install the file from the Scripting menu or copy it by hand to the folder, its path is displayed in the Scripting Shell window, when Workbench is started.

Plugin Input Definition

The wbinputs object from the wb module contains various convenience functions that create plugin input descriptors for the parameters that a plugin can request from Workbench. These parameters are usually related to the active environment, such as the currently loaded model, selected diagram, open SQL editor etc If the requested arguments are not available, the menu entry for the plugin will be disabled.

These should be used in the list given to the input argument of the plugin definition function.

The following is a list of the values that are currently supported:

Plugin Menu Entries

The following keywords can be given to the pluginMenu argument of the plugin definition function:

Text Filter Plugins

A specialized plugin type for text editors is also available. These act as "filters", where the selected text is given to the plugin and after some kind of transformation, it is returned to be reinserted to the text editor, replacing the selection that was given to it. Below is an example of such filter:

@ModuleInfo.exportFilter("wb.text.comment", "Un/Comment Selection")
def commentText(text):
  lines = text.split("\n")
  if lines[0].startswith("-- "):
    return "\n".join((line[3:] if line.startswith("-- ") else line) for line in lines)
  else:
    return "\n".join("-- "+line for line in lines)

This plugin will be accessible from the context menu in code editor/query buffer in the SQL Editor and will comment or uncomment the currently selected text lines. Note that it is not necessary to export the function in a separate statement, as the input parameter is always a string (the selected text) and so is the return value (the string to replace the selection with).

Other Parts of the Documentation

MForms - The Mini Forms Library

The MForms library allows writing basic cross-platform graphical user interfaces. It is accessible from Python through the mforms module (import mforms)

globals - The GRT Globals Tree

Information about the internal object model accessible by plugins and scripts. A list of key nodes in the globals tree is presented.




Plugin Writing Tutorial

In this example we are going to write a simple plugin for the SQL Editor and will highlight how to use the reference documentation to get this done most efficiently.

First, we need to register our plugin as described before, with the common module preamble.

from wb import *
import grt

ModuleInfo = DefineModule(name= "MyModule", author= "My Name", version="1.0")

The idea for this plugin, is to take the take the query in the current query buffer of the SQL Editor, substitute certain special values (for example, %[random:0,100]% or %[oneof:apple,banana,orange]%) and shows it in a new query buffer.

We will start with a placeholder plugin definition. The input to the function is the active SQL Editor object, its class is db_query_Editor. According to Plugin Input Definition, to request the currently active SQL Editor object, wbinputs.currentSQLEditor() must be used. We also want it to show up in the Utilities submenu from the Plugins menu, so from Plugin Menu Entries, can use "SQL/Utilities" as the pluginMenu argument.

@ModuleInfo.plugin("my.plugin.fill_random_query", caption= "Fill in Random Values in Query", input=[wbinputs.currentSQLEditor()], pluginMenu="SQL/Utilities")
@ModuleInfo.export(grt.INT, grt.classes.db_query_Editor)
def fill_random_query(editor):
        return 0

Now, to find out which functions and attributes db_query_Editor offers, we take a look at its entry in the Globals and Classes Reference. In our example we want to access the text in the current SQL Query Tab. For this purpose we use the db_query_Editor::activeQueryBuffer attribute, that will return a reference to a db_query_QueryBuffer object. In that object, we can use the db_query_QueryBuffer::script attribute to access its textual contents. Once the contents are processed, we also want to create a new query buffer and set it's contents to the processed text from the first query buffer. db_query_Editor::addQueryBuffer() can be used to create the new buffer and get a reference to it, from its return value. We then use db_query_QueryBuffer::replaceContents() to set its contents to the query we created:

def process_script(script):
        import re
        import random
        tokens = re.split("(%\[.*?\]%)", script)
        output = []
        for token in tokens:
                out_token = token
                if token.startswith("%[") and token.endswith("]%"):
                        command, sep, args = token[2:-2].partition(":")
                        if command == "oneof":
                                out_token = random.choice(args.split(","))
                        elif command == "random":
                                min_value, sep, max_value = args.partition(",")
                                out_token = "%s" % random.randint(int(min_value), int(max_value))
                output.append(out_token)
        return "".join(output)

# because of a bug in the wbinputs.currentSQLEditor() input     specifier from the wb module 
# in Workbench 5.2.26, we include our own version of it here
def currentSQLEditor():
        arg= grt.classes.app_PluginObjectInput()
        arg.name= "activeSQLEditor"
        arg.objectStructName= "db.query.Editor"
        return arg

@ModuleInfo.plugin("my.plugin.fill_random_query", caption= "Fill in Random Values in Query", input=[currentSQLEditor()], pluginMenu="SQL/Utilities")
@ModuleInfo.export(grt.INT, grt.classes.db_query_Editor)
def fill_random_query(editor):
        active_buffer = editor.activeQueryBuffer
        script = active_buffer.script

        try:
                new_script = process_script(script)     
        except Exception, exc:
                new_script = "Error: %s" % exc

        new_buffer = editor.addQueryBuffer()
        new_buffer.replaceContents(new_script)

        return 0
Here is the complete code in a single file.

Now that the code is ready, we must install it. From the Scripting menu in Workbench, call Install Plugin/Module File... and select the file to be installed.