12.3. Plugins

A Larch plugin is a Python module that adds functionality to Larch at run-time. Plugins are a powerful part of Larch that allow it to be extended without the requiring detailed knowledge of all of Larch’s internals. Generally speaking, plugins will define new functions or data to become part of the Larch framework. Functions defined in plugins can access the Larch interpreter session, including creating or manipulating Groups in Larch’s symbol table. Essentially all the scientific functionality of Larch is implemented as plugins.

There are a few points to consider for writing plugins. First, in order for a plugin function to interact with the running Larch interpreter, it needs a _larch keyword argument. To be clear, the function does not require a _larch keyword argument, but if the function does have a _larch keyword argument, it will be used to pass in the current larch interpreter. Normally, you will only really need the symtable attribute of the _larch variable which holds the symbol table used, but you can interact with any part of the interpreter if you need to.

Second, all functions (or data resources) that are to be added to Larch need to be registered. This is done by defining a function called registerLarchPlugin() that returns a tuple containing the name of the group containing the added functions, and a dictionary with keys used for the names to be put into the Larch symbol table, and values of the functions or data to be used. of Larch symbol. A simple plugin module would look like:

def myfunc(x, y, _larch=None):
    # Note: larch instance passed in to '_larch'
    if _larch is None:
        return
    group = _larch.symtable.create_group(name='created by myfunc')

    group.x = x
    group.y = y
    group.z = 100
    return group

def registerLarchPlugin(): # must have a function with this name!
    return ('mymod', {'func': myfunc})

This would create a top-level Larch group mymod (if it didn’t already exist), and create a function func in this group that held the python function myfunc. To use this function from the Larch interpreter, you would use something like:

larch> out = mymod.func(12, 'a string')
larch> print out.x, out.y, out.z
12  'a string' 100

This plugin simply puts data into a Group, but of course you can do much more complicated work inside the function.

registerLarchPlugin():

register a set of functions or data resources defined in the module into the current Larch interpreter. This function should return a tuple of (GroupName, Symbols_Dictionary), where the Group name is the top-level Group to place the data in, and the Symbols dictionary maps the values (functions or data in the Python module) to names in the Larch Group.

12.3.1. Locations of Plugins

Plugins are meant to be long-lived and reused, and so are not expected to be placed in the current working directory. Plugins are located in the the installed Larch Plugin folder ( $HOME/.larch/plugins/ on Unix or Mac OS X or C:\Users\USERNAME\larch\plugins on Windows).

Plugins in the user’s Larch Plugin folder can be added into the current Larch session with the add_plugin() function.

_builtin.add_plugin(python_file)

add a plugin from the given plugin python file. In contrast to the import statement, add_plugin() will install the resources defined by registerLarchPlugin() every time it is run.

Parameters:python_file – name of Python file containing plugin code.
Returns:True on success, False on error

If the above plugin file is saved in a file named myplugin.py in the user’s Larch Plugin folder, then doing:

larch> add_plugin('myplugin')

will add a top-level group mymod with the func function, as described above. For commonly used plugins, the add_plugin() call can be added to your startup script (init.lar in the User’s Larch folder). Since registerLarchPlugin() is re-applied every time add_plugin() is run, this provides a convenient way to develop and debug plugins.

Many plugins are installed into the Larch system folder. These are organized into sub-folders, and generally each plugin folder contains multiple files (modules) providing Larch functionality.

12.3.2. Customizing Plugins and Folders of Plugins

Plugins are meant to be organized in folders. The standard system plugins have several folders, each with several functions. Generally every file (module) in the folder is treated as a plugin module, and if it has a function registerLarchPlugin(), that will be run to place functions in the Larch interpreter.

There are a few ways to control the plugins beyond the registerLarchPlugin() function. First, each module file can have a initializeLarchPlugin() function that will be run immediately after the plugin is registered to initialize plugin functionality.

larch.initializeLarchPlugin(_larch=None)

initializes a Larch plugin. If defined for a plugin, this function is run immediately after installing all the symbols.

Secondly, you may want to tell larch to look only at certain files within the plugin folder for plugins. To do this, simply include a file named plugins.txt in the plugin folder that lists the files (one per line) to use for plugins.

Finally, a Larch plugin may depend on third party Python modules that may not be installed or available on all systems. This should be considered acceptable – certain plugins may not work on all systems, but that shouldn’t cause problems for the other functionality. To specify which Python modules (and which versions of the modules), a particular plugin depends on, you can include a file requirements.txt in the plugin folder which contains the module name and version strings, one per line. A typical requirements.txt file might look like:

epics>=3.1
scipy>=0.13

to specify which modules and minimal versions for the plugin files in that folder to work. If these requirements are not satisfied, the modules will not be installed.