Contributing

Basic workflow:

Setting up your environment

Set up and activate a virtualenv:

virtualenv gracedb-client-dev
source gracedb-client-dev/bin/activate

Install the package in development mode. In the repository root, run:

python setup.py develop

Then, install some additional tools which are useful for development:

pip install -r requirements-dev.txt

Guidelines

Unit tests

New contributions should have 100% test coverage. If they include interactions with the server, corresponding integration tests should be included, as well. Unit and integration tests are required for the command-line client, too, not just the main Python modules!

Code style

All commits must pass linting checks. The CI configuration does this check after pushing a commit to the remote repository, but it’s a good idea to catch issues locally first.

To help with this, you can install a pre-commit hook for linting with flake8:

flake8 --install-hook=git
git config --bool flake8.strict true

To run the linting process manually, you can do:

flake8 *.py ligo/

from the root of the repository.

Command-line client

If you add some useful, non-private functionality to the client class, something similar should probably be added to the command-line client, as well.

Running tests

This package includes a set of unit tests which cover much of the available functionality. There is also a set of integration tests which can be used to test interactions with a GraceDB server. However, this requires superuser permissions on the server, so it will not be possible for most users. In the future, it may be possible to stand up a GraceDB instance on your local machine and run the integration tests that way, but that is not presently available.

Basic testing

To run the unit tests with the current version of Python, do:

python setup.py test

To run the integration tests, you can do:

python setup.py test --addopts "-m integration"

A pytest mark is also used to distinguish tests of the command-line interface. If you want to run those tests specifically, you can do:

# All CLI-related tests
python setup.py test --addopts "-m cli"

# Only unit tests of CLI
python setup.py test --addopts "-m 'cli and not integration'"

Comprehensive testing

This package includes a configuration for using tox to automate testing with different versions of Python. The current configuration uses Python 2.7 and Python 3.4-3.7, if available on your system.

tox should already be installed from the requirements-dev.txt file. However, if you still need to install it, you can do so with pip:

pip install tox

To run all combinations of unit and integration tests with all versions of Python, go into the root of the repository and do:

tox

To run the unit tests only, with all Python versions:

tox -e $(tox -l | grep unit_test | paste -sd "," -)

To run the client integration tests only, with all Python versions:

tox -e $(tox -l | grep integration_test | paste -sd "," -)

To run all unit and integration tests with a specific Python version:

tox -e $(tox -l | grep py27 | paste -sd "," -)

To run the unit tests with all compatible versions of Python, do:

tox -e $(tox -l | grep unit_test | paste -sd "," -)

Any versions of Python which are included in the tox configuration but not available on your system will be skipped.

Adding commands to the command-line client

The command-line client uses a custom metaclass to facilitate registration of new commands to the base command-line client class. This section gives a brief overview of how to add new commands to the command-line client.

One-part commands

These commands are things like gracedb ping and gracedb show, which only feature a verb and no noun in the base command (an exception is gracedb credentials). These should inherit from ligo.gracedb.cli.commands.base.RegisteredSubCommandBase and be put in ligo/gracedb/cli/commands/subcommands.py. The name attribute defines how the command will be called (gracedb [name]). One-part commands need to be imported in ligo/gracedb/cli/commands/__init__.py to be registered.

Use the existing one-part commands as examples.

Two-part command bases

These are commands like gracedb add and gracedb get, which don’t do anything on their own, but require an additional noun argument to specify what you are adding or getting to complete the command. Commands like this are typically defined in their own file in ligo/gracedb/cli/commands/. A variable called registry should be defined as an empty list just below the imports in this file and assigned to the subcommands attribute of the new command class.

A new command base should inherit from ligo.gracedb.cli.commands.base.RegisteredCommandBase. The name attribute defines how the command will be called (gracedb [name]). Command bases need to be imported in ligo/gracedb/cli/commands/__init__.py to be registered.

Use the existing command bases as examples.

Two-part commands

These are commands like gracedb add event and gracedb get superevent and are associated with a two-part command base. For example, the class which defines gracedb add event (ligo.gracedb.cli.commands.add.AddEventCommand) is defined in the same file as the class which defines gracedb add and is automatically registered in its subcommands attribute using a custom metaclass. The name attribute defines how the command will be called (gracedb [base command name] [name]). These commands should inherit from ligo.gracedb.cli.commands.base.RegisteredSubCommandBase and have their _registry attribute set to be the registry variable declared at the top of the module.

Use the existing two-part commands as examples.