diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..ed6d8e1db --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,6 @@ +# Contribution to MNE-LSL + +Contribution of all sorts are the welcome in MNE-LSL. Please fork the repository +and open a PR with changes applied on your fork for review. See the +[contributing instructions online](https://mne.tools/mne-lsl/stable/development/contributing.html) +to run the documentation build and the unit tests locally. diff --git a/doc/changes/1.0.rst b/doc/development/changes/1.0.rst similarity index 100% rename from doc/changes/1.0.rst rename to doc/development/changes/1.0.rst diff --git a/doc/changes/1.1.rst b/doc/development/changes/1.1.rst similarity index 100% rename from doc/changes/1.1.rst rename to doc/development/changes/1.1.rst diff --git a/doc/changes/1.2.rst b/doc/development/changes/1.2.rst similarity index 100% rename from doc/changes/1.2.rst rename to doc/development/changes/1.2.rst diff --git a/doc/changes/1.3.rst b/doc/development/changes/1.3.rst similarity index 100% rename from doc/changes/1.3.rst rename to doc/development/changes/1.3.rst diff --git a/doc/changes/1.4.rst b/doc/development/changes/1.4.rst similarity index 100% rename from doc/changes/1.4.rst rename to doc/development/changes/1.4.rst diff --git a/doc/changes/1.5.rst b/doc/development/changes/1.5.rst similarity index 100% rename from doc/changes/1.5.rst rename to doc/development/changes/1.5.rst diff --git a/doc/changes/authors.inc b/doc/development/changes/authors.inc similarity index 100% rename from doc/changes/authors.inc rename to doc/development/changes/authors.inc diff --git a/doc/changes/index.rst b/doc/development/changes/index.rst similarity index 100% rename from doc/changes/index.rst rename to doc/development/changes/index.rst diff --git a/doc/changes/latest.rst b/doc/development/changes/latest.rst similarity index 100% rename from doc/changes/latest.rst rename to doc/development/changes/latest.rst diff --git a/doc/changes/latest.rst.template b/doc/development/changes/latest.rst.template similarity index 100% rename from doc/changes/latest.rst.template rename to doc/development/changes/latest.rst.template diff --git a/doc/development/contributing.rst b/doc/development/contributing.rst new file mode 100644 index 000000000..35bdf8081 --- /dev/null +++ b/doc/development/contributing.rst @@ -0,0 +1,136 @@ +.. include:: ../links.inc + +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: + +.. code-block:: console + + $ 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: + +.. code-block:: console + + $ pre-commit install + +Once installed, the hooks will run automatically before each commit. If you want to +manually run the hooks, you can use: + +.. code-block:: console + + $ 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: + +.. code-block:: console + + $ 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: + +.. code-block:: console + + $ make view + +Finally, building the tutorials and examples is a slow process. To skip running the +examples and tutorials, run: + +.. code-block:: console + + $ make html-noplot + +Tests +----- + +The unit tests are written using `pytest`_ and can be run from the root of the +repository with: + +.. code-block:: console + + $ 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 +:class:`~mne_lsl.lsl.StreamInlet` and :class:`~mne_lsl.lsl.StreamOutlet` can be tricky. +Here are a couple of tips to help you write reliable tests: + +- If you create a mock LSL stream with :class:`~mne_lsl.player.PlayerLSL`, use the + fixture ``chunk_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 :class:`~mne_lsl.stream.StreamLSL` or :class:`~mne_lsl.player.PlayerLSL` have + underlying LSL inlets and outlets. Don't forget to call + :meth:`mne_lsl.stream.StreamLSL.disconnect` followed by + :class:`mne_lsl.player.PlayerLSL.stop` at the end of your test. + +- If you need to create :class:`~mne_lsl.lsl.StreamInlet` or + :class:`~mne_lsl.lsl.StreamOutlet` + directly, use the ``close_io`` fixture which returns a function to call at the end of + your test to remove the inlets 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. + +.. _fork the mne-lsl repository: https://github.com/mne-tools/mne-lsl/fork +.. _open a pull request: https://github.com/mne-tools/mne-lsl/compare +.. _numpydoc: https://numpydoc.readthedocs.io +.. _pre-commit: https://pre-commit.com +.. _pytest: https://docs.pytest.org +.. _sphinx: https://www.sphinx-doc.org diff --git a/doc/index.rst b/doc/index.rst index 09f360b12..9aa4eccf0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -69,4 +69,10 @@ The development of ``MNE-LSL`` is supported by the resources/implementations.rst generated/tutorials/index.rst generated/examples/index.rst - changes/index.rst + +.. toctree:: + :hidden: + :caption: Development + + development/contributing.rst + development/changes/index.rst diff --git a/doc/links.inc b/doc/links.inc index 9374fad06..1adf4da87 100644 --- a/doc/links.inc +++ b/doc/links.inc @@ -25,6 +25,7 @@ .. mne +.. _code of conduct: https://github.com/mne-tools/.github/blob/main/CODE_OF_CONDUCT.md .. _mne stable: https://mne.tools/stable/index.html .. _mne installers: https://mne.tools/stable/install/installers.html