Distributing your own plugin package#

If you are looking to customize glue for your own use, you don’t necessarily need to create a plugin package - instead you can just use a config.py file as described in Configuring Glue via a startup file. However, if you are interested in sharing your customizations with others, then the best approach is to develop and distribute a plugin package.

Plugin packages use the same mechanism of registering customizations described in Customizing your Glue environment as you would if you were using a config.py file - the only real difference is the file structure you will need to use. To make things easier, we provide a template plugin package at glue-viz/glue-plugin-template to show you how files should be organized.

Required files#

To start with, any Python code that is part of the plugin package should be placed in a directory with the name of the module for the plugin. In our template, this is the myplugin directory - for some of the real plugins we have developed in the past, this is for example glue_medical or glue_geospatial. This directory should contain at least one Python file that contains the customizations that you would otherwise have put in your config.py file. In the template example, this is the data_viewer.py file which contains a custom data viewer.

In addition to this file (or multiple files), you will need an __init__.py file, which should contain a setup function. This function is used to register any customizations with glue. In this function, you should import any files containing customizations. If the customizations use a decorator to be registered (e.g. @data_factory or @menubar_plugin), then you are all set. Otherwise, for registering e.g. custom_viewers, the setup function should also do the registration - in the template, this looks like:

def setup():
    from .data_viewer import MyViewer
    from glue_qt.config import qt_client
    qt_client.add(MyViewer)

Finally, at the root of the package, you will need a setup.py file similar to the one in the template (you can copy it over and edit the relevant parts). One of the important parts is the definition of entry_points, which is the part that tells glue that this package is a plugin:

entry_points = """
[glue.plugins]
myplugin=myplugin:setup
"""

The entry in [glue.plugins] has the form:

plugin_name=module_name:setup_function_name

In general, to avoid confusion, the plugin_name and module_name should both be set to the name of the directory containing the code (myplugin in our case).

Once you have this in place, you should be able to install the plugin in ‘develop’ mode (meaning that you can then make changes and have them be updated in the installed version without having to re-install every time) with:

pip install -e .

You can then start up glue with:

glue -v

The startup log then contains information about whether plugins were successfully loaded. You should either see something like:

INFO:glue:Loading plugin myplugin succeeded

Or if you are unlucky:

INFO:glue:Loading plugin myplugin failed (Exception: No module named 'numpyy')

In the latter case, the exception should help you figure out what went wrong. For a more detailed error message, you can also just import your plugin package and run the setup function:

python -c 'from myplugin import setup; setup()'

Optional files#

The only files that are really required are the directory with the source code and the setup.py file - however, you should make sure you also include an open source license if you are planning to distribute the package, as well as a README file that describes your package, its requirements, and how to install and use it.

Consider also adding tests (using e.g. the pytest framework), as well as setting up continuous integration services such as Travis to run the tests any time a change is made. Describing how to do this is beyond the scope of this tutorial, but there are plenty of resources online to help you do this.

Distributing the package#

Since your package follows the standard layout for packages, you can follow the Packaging Python Projects guide to release your package and upload it to PyPI. The usual release process for glue plugins is as follows:

  1. Start off by editing the changelog (if present) and change the release date from unreleased to today’s date, in the YYYY-MM-DD format, for example:

    0.2 (2019-02-04)
    ----------------
    
  2. Edit the version.py file in your package to not include the .dev0 suffix, e.g.:

    version = '0.2'
    
  3. Commit the changes, e.g.:

    git add CHANGES.rst */version.py
    git commit -m "Preparing release v0.2"
    
  4. Remove any uncommitted files/changes with:

    git clean -fxd
    
  5. Now create the release with:

    python setup.py sdist
    

    Provided you don’t have any C extensions in your package, you can also make a so-called ‘wheel’ release:

    python setup.py bdist_wheel --universal
    
  6. Go inside the dist directory and use the twine tool to upload the files to PyPI:

    cd dist
    twine upload *.tar.gz *.whl
    
  7. Optionally tag the release in git with:

    git tag -m v0.2 v0.2
    
  8. Add a new section in the changelog file for the next release:

    0.3 (unreleased)
    ----------------
    
    - No changes yet.
    

    and update the version.py file to point to the next version, with a .dev0 suffix:

    version = '0.3.dev0'
    
  9. Finally, commit the changes and push to GitHub:

    git add CHANGES.rst */version.py
    git commit -m "Back to development: v0.3"
    git push --tags upstream master
    

If you are interested in including your package as a conda package in the glueviz channel, please let us know by opening an issue at glue-viz/conda-dev.