Contributing to Otripy
Contributions are welcome: bug reports and ideas in the issues, code through pull requests. The planned work is in the roadmap.
Development setup
Otripy uses uv (installation). From a clone of the repository:
uv sync # creates .venv with Otripy and the development tools
uv run otripy # runs Otripy from the sources
Otripy supports Python 3.10 and later: avoid syntax and standard library features of newer versions.
Tests and lint
uv run pytest # all tests
uv run pytest tests/test_journey.py # one file
uv run pytest tests/test_journey.py::test_load_legacy_list # one test
uv run ruff check src tests # lint
The tests run without a display (Qt's offscreen platform) and without network access to Nominatim or Nextcloud, which are replaced by fakes. A few notes for writing tests:
- Journey files of each supported shape are in
tests/fixtures/; use thefixture_textfixture to read them. - Tests that create the main window must replace modal dialogs (
QMessageBox,QFileDialog) withmonkeypatch, or the run blocks: seetests/test_file_handling.py. - The JavaScript generated for the map is syntax-checked with Node.js when it is installed.
GitHub Actions runs the lint and the tests on Linux, Windows and macOS, with Python 3.10 and 3.13, for every pull request.
Pull requests
- Fork the repository and create a branch (
git checkout -b feature-name). - Make your changes, with tests for new behavior and bug fixes.
- Check that
uv run pytestanduv run ruff check src testspass. - Add a line to the Unreleased section of CHANGELOG.md for user-visible changes.
- Push your branch and open a pull request.
Changes to the journey file format must follow the rules at the end of the file format description.
Translations
Texts shown to users must be translatable, with self.tr() or QCoreApplication.translate(); after changing them, run uv run python scripts/translations.py to update the translation files. The translators' guide explains how to translate Otripy and how to write translatable code.
Documentation
The user guide is published at https://kleag.github.io/otripy/ from the docs/ directory with MkDocs Material. To preview it:
uv run --group docs mkdocs serve
It is published by GitHub Actions on every push to main that changes it.
Releases
Versions are managed with bumpver, which updates the version in pyproject.toml and src/otripy/__init__.py, then commits, tags and pushes:
uv run --with bumpver bumpver update --patch # or --minor, --major
The changelog's Unreleased section must list the release's changes: bumpver's pre-commit hook (scripts/release_changelog.py) files them under the new version and date, and stops the release if the section is empty. If it stops, undo the version changes with git checkout -- pyproject.toml src/otripy/__init__.py.
The tag (MAJOR.MINOR.PATCH) starts the release workflow, which:
- publishes the sdist and wheel to PyPI (trusted publishing, no token);
- builds the Windows installer (
.msi) and the macOS disk image (.dmg) with Briefcase; - builds the Linux AppImage with PyInstaller and appimagetool;
- attaches all of them to a GitHub release.
Run the Release workflow by hand (Actions → Release → Run workflow) to build everything without publishing.
Building the AppImage locally
The AppImage is built on Ubuntu 22.04, the oldest base that current PySide6 versions support. With Docker, from the repository root:
docker run --rm -v "$PWD:/src" -w /src -e HOST_UID="$(id -u):$(id -g)" \
ubuntu:22.04 packaging/linux/build-appimage.sh
The result is dist/Otripy-<version>-x86_64.AppImage. The build runs otripy --self-test on the packaged application, which checks headless that it has everything it needs; you can run it on any installed Otripy too.