Contributing

Questions

If you have questions about using Mido, contributing code or suggestions for how to make contributing easier, please write at https://github.com/mido/mido/discussions.

Bugs & Feature Requests

Note

If you don’t have a precise idea, please use the questions section outlined above instead of opening an issue.

If you encounter a bug that is reproducible or want to suggest a new feature - including its implementation details - that would fit the project nicely, feel free to open an issue at https://github.com/mido/mido/issues

Please provide as much information as possible to allow us to analyze, including but not limited to:

  • Operating system name & version

  • Python version

  • mido package version & installation method (Distribution repository, PyPI, source…)

  • backend used (amidi, portmidi, rtmidi, PyGame… Defaults to python-rtmidi.)

Forking & Pull Requests

The project welcomes all contributions!

If you wish to make a change, be it code or documentation, please fork the repository from https://github.com/mido/mido and send your pull request to https://github.com/mido/mido/pulls.

Your changes will be reviewed by a maintainer and integrated for publication in the next version of mido once approved.

Installation

Users

For general usage, see Installing.

If you wish to install from source, run the following command from the sources root directory:

python3 -m pip install --editable .

Or, alternatively if you want to use ports:

python3 -m pip install --editable .[ports-rtmidi]

Note

No support will be provided if you install from source.

Developers

Warning

We recommend that you first setup a virtual environment to avoid conflicts with already installed files.

Then, to install the development dependencies, you can run the following command from inside your virtual environment:

python3 -m pip install --editable .[dev]

Or, alternatively, if you want to use ports:

python3 -m pip install --editable .[dev,ports-rtmidi]

This will install all needed dependencies for linting, testing, documentation generation and publishing releases.

Code Checks

Note

The following code checks are done automatically using a GitHub Actions Workflow (Defined in .github/workflow/tests.yml) for each push to the main branch and each Pull Request.

It’s good practice to check your changes locally before submitting.

Linting

Linting is done with ruff. Its configuration can be found in pyproject.toml.

You can lint your code using:

ruff check .

Testing

pytest is used for unit testing. The tests are found in tests/test_*.py. The default configuration is declared in the tool.pytest.ini_options section of pyproject.toml.

The test suite can be run using the command:

pytest

Checking the Release Manifest

To make sure the repository and source code manifest (.MANIFEST.in) are in sync:

check-manifest --verbose

Building the Documentation

The documentation is generated using Sphinx.

To generate the HTML documentation:

sphinx-build -j auto -q -W -E --keep-going docs docs/_build

If you wish to build a PDF version for local use:

  1. Install a LaTeX distribution

  2. Install ImageMagick

  3. use:

    sphinx-build -M latexpdf docs docs/_build
    

You’ll find the resulting PDF file at docs/_build/latex/Mido.pdf.

Once generated and copied in a safe place, you may want to remove the build artifacts:

sphinx-build -M clean docs docs/_build

Testing MIDI File Support

Test Files

The Lakh MIDI Dataset is a great resource for testing the MIDI file parser.

Releasing

The processes are now automated.

Note

The whole team has access to manual publishing to PyPI and Read the Docs in case of automation defect.

Documentation

To generate the official documentation, we use Read the Docs integration services for GitHub. Every time a new commit is pushed or merged onto our main development branch on GitHub, the latest version of the documentation is updated by Read the Docs. Each time a new version is tagged, the new documentation version is created, built, published and eventually promoted to stable following Semantic Versioning. The stable version of the documentation is the one served by default if no specific version is chosen.

We also build a mirror of the current main development branch documentation using a GitHub Workflow and hosted on GitHub pages.

All of this is defined by .github/workflow/documentation.yml

Package

The process uses GitHub Action Workflow defined by .github/workflow/release.yml and is triggered upon receiving a tag.

Preparation

Make sure all the tests pass, documentation has been updated and everything is in good order before proceeding.

Note

The version number should be PEP 440 & SemVer compliant.

X.Y.Z is the version, for example 1.1.18 or 1.2.0.

  1. update the changelog in docs/changes.rst. The following commands may prove useful to retrieve all Pull Requests & all commits:

    previous_release_tag=git describe --abbrev=0
    git log --oneline --merges --reverse "${previous_release_tag}.."
    git log --oneline --no-merges --reverse "${previous_release_tag}.."
    
  2. update version and date in docs/changes.rst

  3. commit the changes:

    git commit -a -c "Prepare <X.Y.Z> release."
    
  4. set the version number by tagging the release:

    git tag -a <X.Y.Z> -m "mido version <X.Y.Z>"
    

    Note

    We use an annotated tag here to retain all information about the tagger and create a proper object in the GIT database instead of a commit alias.

  5. don’t forget to push your changes including the tags to GitHub to trigger the auto-release process:

    git push --tags
    

Manual steps (Recovery)

Warning

Only use if the automatic process fails for some reason.

  1. Prepare a clean environment:

    git clone --branch <X.Y.Z> --single-branch https://github.com/mido/mido mido-<X.Y.Z>
    cd mido-<X.Y.Z>
    python3 -m venv mido-build
    
  2. Build:

    source mido-build/bin/activate
    python3 -m pip install --upgrade pip setuptools wheel build twine
    python3 -m build
    
  3. Publish on Test PyPI:

    python3 -m build
    twine upload --repository testpypi dist/*
    
  4. Check that the published package is good:

    python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps mido
    python3 -c "import mido; print(mido.version_info)"
    

    Todo

    Now would be a good time to run some integration tests once we have them.

  5. Publish on PyPI:

    twine upload dist/*
    

    Warning

    This is the most critical step of the process. This cannot be undone. Make sure everything is in good order before pressing the “big red button”!