Contribution guide๐
Thanks for taking the time to contribute! MNE-LSL is an open-source project sustained mostly by volunteer effort. We welcome contributions from anyone as long as they abide by our Code of Conduct.
You can propose a change; a bugfix, a docstring improvement or a new feature; by following those steps:
Fork the MNE-LSL repository on GitHub
Clone your fork locally
(optional, recommended) Create a new branch for your changes
Make your changes locally and push them to your fork
Open a pull request with a clear title and description
Install in editable mode๐
To modify MNE-LSL, it is recommended to install it in a separate environment in editable mode. This way, you can test your changes without having to reinstall the package each time. To install MNE-LSL in editable mode, run:
$ pip install -e .[all]
Note
The [all]
extra installs all optional dependencies, including those required for
testing and documentation.
Code style๐
MNE-LSL enforces style rules which are checked by the pre-commit framework. The rules
are configured in the projectโs pyproject.toml
. To install the pre-commit hooks,
run:
$ pre-commit install
Once installed, the hooks will run automatically before each commit. If you want to manually run the hooks, you can use:
$ pre-commit run --all-files
Note
If a PR is opened with failing pre-commit checks, the CIs will attempt to fix the failures automatically with an autofix commit.
Documentation๐
The documentation uses Sphinx and numpydoc to generate the HTML pages. The
numpydoc convention is used. To build the documentation locally, navigate to the
doc
directory and run:
$ make html
The HTML pages will be generated in the doc/_build/html
directory. You can run the
following command to open a browser with the documentation:
$ make view
Finally, building the tutorials and examples is a slow process. To skip running the examples and tutorials, run:
$ make html-noplot
Tests๐
The unit tests are written using pytest and can be run from the root of the repository with:
$ pytest mne_lsl
When adding a feature or fixing a bug, it is important to write a short test to ensure
that the code behaves as expected. Separate features should be tested in separate tests
to help keep the test function code short and readable. Finally, a test should use short
files and run as quickly as possible. Any tests that takes more than 5 seconds to run
locally should be marked with the @pytest.mark.slow
decorator.
Tests are stored in the tests
directory in each module. As much as possible, the
tests within a module should not test a different module, but this is obviously not
simple or mandatory as many modules require the creation of mock LSL stream to run the
tests.
Fixtures used in a single module should be defined within the module itself. If a
fixture is used in multiple modules, it should be defined in the mne_lsl/conftest.py
file.
Finally, writing reliable tests with mock LSL stream or
StreamInlet
and StreamOutlet
can be tricky.
Here are a couple of tips to help you write reliable tests:
If you create a mock LSL stream with
PlayerLSL
, use the fixturechunk_size
which returns a large chunk size suitable for CIs.If you need to create inlets or outlets, always close the inlets first before closing or destroying the outlets.
Note
A
StreamLSL
orPlayerLSL
have underlying LSL inlets and outlets. Donโt forget to callmne_lsl.stream.StreamLSL.disconnect()
followed bymne_lsl.player.PlayerLSL.stop()
at the end of your test.If you need to create
StreamInlet
orStreamOutlet
directly, use theclose_io
fixture which returns a function to call at the end of your test to remove the inlets and outlets.If the objects in your test use separate threads for acquisition or processing, donโt forget to include sleep periods to ensure that the threads have time to work.