Contributing¶
Contributions are welcome. This page covers the local workflow; the same checks run in CI.
Setup¶
You also need ffmpeg on your PATH for any end-to-end run (the test suite
itself does not need it — see below).
Quality gate¶
Four checks must pass before a change is merged. They mirror the CI workflow:
pytest # tests
ruff check . # lint (includes import sorting + docstring rules)
black --check . # formatting
pyright src # type checking of the public surface
Autofix formatting and the fixable lint issues with:
Tests¶
Tests live in tests/test_core.py and run in well under a second. They exercise
the whole text pipeline (parsing, scoring, DP alignment, formatting) and the
library API using synthetic WordTimestamp data and an injected fake Whisper
model — so no audio files, no model download, and no ffmpeg are required.
When adding behavior, add a test alongside the existing classes (for example
TestDPAlign, TestAlignFacade, TestLRCFormatter).
Type checking¶
The package ships a py.typed marker, so the public API is type-checked.
pyright src must stay clean; keep annotations correct on anything exported
from syncalong/__init__.py.
Docstrings¶
Every public class and function uses Google-style docstrings
(Args: / Returns: / Raises: / Attributes:). Ruff's pydocstyle rules
enforce their presence with the google convention. The API reference on this
site is generated from these docstrings by
mkdocstrings, so a good docstring is the
documentation.
Text normalization¶
textnorm.normalize() is the single source of truth shared by the lyrics parser
and the transcriber. Never reimplement normalization locally — both sides of
the aligner must normalize identically or fuzzy matching silently degrades.
Building the docs¶
mkdocs serve # live-reload preview at http://127.0.0.1:8000
mkdocs build # render the static site into ./site
Releasing¶
Releases are automated and driven entirely by git tags (see versioning):
- Update
CHANGELOG.mdwith the new version's notes. -
Tag the release and push the tag:
-
The
releaseworkflow builds the sdist + wheel, publishes them to PyPI via Trusted Publishing (OIDC, no stored token), and creates a GitHub Release with the artifacts attached.
Tags should be of the form vMAJOR.MINOR.PATCH.
Versioning¶
The version is not stored in the source tree. It is derived from the latest git tag by setuptools-scm:
- a checkout at tag
v0.1.0builds as version0.1.0; - commits after a tag build as
0.1.1.devN+g<hash>.
So the only thing you bump is the tag.