Thank you for your interest in contributing to the Musical Gestures Toolbox for Python!
- Development Setup
- Code Style
- Type Hints
- Tests
- Documentation
- Pull Request Workflow
- Adding New Features
- Python ≥ 3.10
- FFmpeg must be on your
PATH - Git
# 1. Fork and clone
git clone https://github.com/YOUR_USERNAME/MGT-python.git
cd MGT-python
# 2. Create a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install the package in editable mode with development dependencies
pip install -e ".[dev]"
# 4. Verify the installation
python -c "import musicalgestures; print('OK')"nox provides isolated, reproducible sessions:
pip install nox # one-time install
nox -s tests # run the test suite on Python 3.12
nox -s lint # ruff linting + format check
nox -s typecheck # mypy type checking
nox -s coverage # pytest + coverage report
nox -l # list all available sessionsWe use ruff for linting and formatting. Run checks before committing:
ruff check musicalgestures/
ruff format musicalgestures/Key conventions:
- Line length: 100 characters.
- Imports: standard library first, then third-party, then local. One import per line.
- Strings: double quotes for docstrings; prefer single quotes for non-docstring strings.
- Logging: use
logging.getLogger(__name__)inside modules; never use bareprint()for library output. - Progress bars: use
tqdmor the existingMgProgressbarwrapper.
All new code must include type annotations (PEP 484/526).
from __future__ import annotations
def compute_qom(frame: np.ndarray, threshold: float = 0.05) -> float:
...Check annotations with mypy:
mypy musicalgestures/ --ignore-missing-importsTests live in tests/ and are run with pytest.
pytest tests/ -v # run all tests
pytest tests/ -k "motion" # run tests matching "motion"
pytest tests/ --cov=musicalgestures --cov-report=term-missing- Add a new test file
tests/test_<feature>.py. - Use
pytest.fixturefor shared resources. - Assert on array shapes, file existence, and return types – not just that code runs without error.
- Mark slow tests with
@pytest.mark.slowand skip in fast CI runs.
Example:
import numpy as np
import pytest
from musicalgestures._features import MgFeatures
def test_mgfeatures_shape():
feat = MgFeatures({"qom": np.array([1.0, 2.0, 3.0])}, sr=25.0)
assert feat.shape == (1, 3)
assert feat.to_numpy().shape == (1, 3)
def test_mgfeatures_round_trip(tmp_path):
feat = MgFeatures({"a": np.arange(5.0), "b": np.ones(5)}, sr=10.0)
p = tmp_path / "feat.json"
feat.to_json(p)
feat2 = MgFeatures.from_json(p)
np.testing.assert_array_equal(feat["a"], feat2["a"])Docs are built with MkDocs:
pip install mkdocs mkdocs-material
mkdocs serve # live preview at http://127.0.0.1:8000
mkdocs build --clean # build static site in site/Use NumPy-style docstrings consistently:
def my_function(x: np.ndarray, threshold: float = 0.5) -> float:
"""One-line summary.
Extended description (optional).
Parameters
----------
x:
Input array.
threshold:
Value between 0 and 1. Default: 0.5.
Returns
-------
float
The result.
Examples
--------
>>> my_function(np.array([1, 2, 3]), threshold=0.3)
2.0
"""-
Branch off
master:git checkout -b feature/my-feature
-
Make focused commits – one logical change per commit. Use conventional commits format:
feat: add MgFeatures.to_zarr() method fix: handle empty video in MgVideoReader docs: update CONTRIBUTING.md -
Run all checks before pushing:
nox -s lint tests
-
Open a Pull Request against
masterand fill in the PR template.- Describe what changed and why.
- Reference any related issues.
- Add or update tests.
-
CI must pass before merging.
- Create
musicalgestures/_myfeature.pywith a standalone function. - Import it in
musicalgestures/_video.pyvia thefrom ... import ... as ...pattern used by existing methods. - Export it from
musicalgestures/__init__.pyif it is a public class or function. - Add a test in
tests/test_myfeature.py. - Document it in
docs/.
Add the value to the appropriate class in musicalgestures/_enums.py. Enum members support case-insensitive string construction, so no existing code will break.
- Add it to the appropriate extras group in
pyproject.toml. - Guard the import with
try / except ImportErrorand raiseMgDependencyErrorwith a helpful message. - Document the install command in the docstring.