This document defines FVH's programming conventions when using Python programming language. Note that this is work-in-progress project.
If you don't agree with some point, then suggest a change, and we'll discuss it.
We support "security" and "bugfix" versions which are mentioned in the Status of Python versions page, but consider using two latest versions which are currently Python 3.13 and 3.14 (updated March 2026). If your deployment environment doesn't support these, consider installing the latest Python or using Docker containers, where you should always use the latest version of Python.
Of course, if your machine learning project requires Python 3.11 or something else, you can use it.
Use uv venv to create virtual environments. UV is a fast Python package installer
and resolver written in Rust. It offers several advantages over traditional tools:
- Up to 10-100x faster than pip for installations
- Built-in dependency resolution that's more reliable than pip
- Native support for modern package formats and lockfiles
- Lower memory usage and better system resource utilization
- Automatic virtual environment management
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or on macOS
brew install uv
# Create new virtual environment
uv venv # optional: --python 3.13
# Activate virtual environment
source .venv/bin/activateUV replaces both venv and pip functionality with improved performance. Do not use virtualenv, pyenv, or other alternatives when creating virtual environments in scripts.
Install default dependencies and development dependencies in active virtual environment in one go:
uv sync --group devUse uv run to run commands inside the virtual environment without manually activating it:
uv run pytest
uv run ruff check .
uv run mypy src/Use uv lock to generate and update the lockfile (uv.lock). The lockfile ensures
reproducible installations across environments. Commit uv.lock to version control.
# Generate or update lockfile
uv lock
# Update a specific dependency
uv lock --upgrade-package fastapiIf you are the one and only person who is writing and viewing the code in your project, it is highly recommended to use tools listed below. You can safely try all commands to see what they would do.
Many IDEs (PyCharm, VSCode, Cursor, etc.) have plugins for Ruff, so you can use it without additional setup.
Ruff is an extremely fast Python linter and code formatter, written in Rust. It replaces multiple tools (like black, isort, flake8, etc.) with a single, unified solution.
Check and fix code style:
ruff check --fix .
Format code:
ruff format .
Configuration is already set up in the project's pyproject.toml file. See the configuration for detailed rules and settings.
Pre-commit hooks are mandatory for all repositories under Forum Virium Helsinki. These hooks:
- Automatically run Ruff, mypy, and other checks before each commit
- Ensure code quality standards are met
- Prevent commits that don't meet the required standards
- Save time by catching issues early in the development process
To set up pre-commit:
- Copy .pre-commit-config.yaml to your repository root
- Install and activate pre-commit:
uv pip install pre-commit && pre-commit installIf you have already run uv sync --group dev, you can skip the installation step. You can update the pre-commit hooks by running: pre-commit autoupdate.
The pre-commit configuration includes Ruff, mypy type checking, and other essential checks. You can find the complete configuration in the example .pre-commit-config.yaml.
mypy is a static type checker for Python that helps catch type-related errors before runtime. Type checking is mandatory for all new projects.
Key benefits:
- Catches type errors at development time
- Improves code documentation through type annotations
- Makes refactoring safer and easier
- Enhances IDE support with better autocomplete
Run type checking manually:
mypy src/
Configuration is set up in pyproject.toml with strict settings enabled. mypy is also automatically run as part of pre-commit hooks.
We are actively evaluating alternative type checkers. If you find one of these better suited for your project, you are free to use it instead of mypy:
- pyright — Microsoft's type checker, fast and widely used, excellent VSCode integration via Pylance.
- basedpyright — a fork of pyright with additional strictness options and quality-of-life improvements.
Both are valid choices and can be configured in pyproject.toml. If you switch, update the
pre-commit hooks accordingly and document the choice in the project README.
We use sentry.io to track errors in our production deployments. Sentry provides real-time error tracking and monitoring:
- Automatic error capturing and reporting
- Detailed stack traces and context
- Performance monitoring
- Release tracking and source maps
To set up Sentry in your project:
- Ask sysadmins for your project's Sentry DSN
- Install the SDK:
uv add sentry-sdk - Initialize Sentry in your application:
import sentry_sdk
sentry_sdk.init(
dsn="your-dsn-here",
traces_sample_rate=0.1, # Adjust based on traffic — 1.0 captures everything
environment="production"
)Note: A traces_sample_rate of 1.0 captures every transaction and can be expensive
in high-traffic applications. Start with 0.1 (10%) and adjust based on your needs.
Code review by a colleague is recommended, especially when you're new to the project or working on complex features. While not always mandatory for minor changes, it helps to:
- Catch potential issues early
- Ensure code follows project standards
- Share knowledge within the team
When in doubt, always ask for a review. Your colleagues are there to help!
We use a simplified branching strategy focused on the main branch:
- Main branch is used for active development
- Feature/bugfix branches are created from
mainfor specific changes - Branch naming:
feature/description-of-changeandbugfix/issue-description - Aim for short-lived branches and merge often to avoid conflicts
- When working alone on initial development, you can commit directly to
main
- Use rebase or squash when merging pull requests
- Avoid merge commits to keep commit history linear and clean
- This makes it easier to track changes and debug issues later
Pull requests (PRs) are recommended for code review, but the approach can be flexible based on project size and team:
For larger projects or team collaborations:
- PRs are mandatory for all changes
- Formal code review process ensures quality and knowledge sharing
- All changes must be approved before merging
For smaller projects or personal work:
- You can commit directly to
mainduring initial development phases - Use PRs when you want feedback or for significant changes
- Consider creating PRs even for solo work to document important changes
Benefits of using PRs:
- Maintains code quality through peer review
- Catches potential issues early in development
- Provides documentation of changes and reasoning
- Keeps the team informed about ongoing work
Releases are published directly from stable points in the main branch:
- No separate release branches needed
- It's acceptable for
mainto be temporarily broken during development - Release when you reach a stable, tested state
- Tag releases with semantic versioning (e.g.,
v1.2.3)
The release process can be fully automated using CI/CD tools. This automation works best with:
Conventional Commits:
- Use standardized commit message format
- Examples:
feat: add user authentication systemfix: resolve database connection timeoutdocs: update installation instructionschore: update dependencies
Automated benefits:
- Automatic version number bumping based on commit types
- Generated release notes from commit messages
- Automated changelog updates
- Consistent release process across projects
Commit types:
feat: New features (minor version bump)fix: Bug fixes (patch version bump)BREAKING CHANGE: Breaking changes (major version bump)docs,style,refactor,test,chore: No version bump
This approach reduces manual work and ensures consistent, documented releases.