Thank you for your interest in contributing to PyHamcrest! This guide will help you get started.
- Development Setup
- Running Tests
- Code Style and Linting
- Type Checking
- Adding Changelog Entries
- Submitting Pull Requests
- Release Process
- Python 3.10 or later (Python 3.14 recommended for development)
- Git
- Fork and clone the repository:
git clone https://github.com/YOUR-USERNAME/PyHamcrest.git
cd PyHamcrest- Install development dependencies:
We recommend using uv for fast dependency resolution:
pip install uv
uv pip install -e ".[dev]"Or using pip directly:
pip install -e ".[dev]"- Install pre-commit hooks:
pre-commit installThis ensures code style checks run automatically before each commit.
Run tests with pytest:
pytestRun a specific test file:
pytest tests/hamcrest_unit_test/core/isequal_test.pyRun a specific test:
pytest tests/hamcrest_unit_test/core/isequal_test.py::TestClass::test_nameRun tests with coverage:
coverage run -m pytest
coverage reportWe use tox to test across multiple Python versions:
# Test all available Python versions (skips missing interpreters)
tox -s
# Test specific Python version
tox -e py312
# Test with numpy support
tox -e py312-numpyIMPORTANT: Always run tox -s before submitting a pull request to verify tests pass across all available Python versions. The -s flag skips missing interpreters.
- Python 3.10, 3.11, 3.12, 3.13, 3.14
- PyPy 3.11
PyHamcrest uses automated code formatting and linting:
Code is formatted with Black and Ruff.
Run pre-commit hooks on all files:
pre-commit run --all-filesOr via tox:
tox -e lint- Line length: 100 characters
- The codebase intentionally uses star imports (
from module import *) to provide a clean public API - Import order is managed by isort with a custom "hamcrests" profile
PyHamcrest includes type annotations and is checked with mypy.
Run type checking:
mypy src/Or via tox:
tox -e typingType hints are tested using mypy with special test files in tests/type-hinting/. These files use a YAML format to test that type annotations work correctly. If you're adding or modifying type annotations, consider adding corresponding type tests.
REQUIRED: Every pull request that changes functionality must include a changelog entry.
Exception: Documentation-only changes (README, CONTRIBUTING, etc.) do not require changelog entries.
PyHamcrest uses towncrier to manage the changelog.
For every PR that changes code or functionality, create a changelog fragment file in the changelog.d/ directory:
Format: changelog.d/{issue_or_pr_number}.{category}.rst
Categories:
feature- New features or enhancementsbugfix- Bug fixesmisc- Miscellaneous changes (CI, docs, refactoring, etc.)
Example: If your PR is #123 and adds a new feature, create:
changelog.d/123.feature.rst:
Add support for matching custom objects with has_attributes matcher.Tips:
- Keep descriptions concise and user-focused
- Write in the past tense ("Added", "Fixed", not "Add", "Fix")
- Don't include implementation details unless relevant to users
- The issue/PR number in the filename will be automatically linked in the generated changelog
- ✅ Run tests:
tox -s - ✅ Run linting:
pre-commit run --all-files - ✅ Run type checking:
tox -e typing - ✅ Add changelog entry (REQUIRED for code changes) - see Adding Changelog Entries
- ✅ Update documentation if needed
When you create a pull request, GitHub Actions will automatically run:
- Tests on Python 3.10, 3.11, 3.12, 3.13, 3.14, and PyPy 3.11
- Tests on Linux, macOS, and Windows
- Linting checks
- Type checking
- Documentation build
The CI workflow runs on:
- All pull requests to
mainormaster - Pushes to
main,master, or branches starting withci-testing-*
- Branch naming: Use descriptive names like
fix-issue-123oradd-new-matcher - Commit messages: Write clear, descriptive commit messages
- PR description: Explain what changes you made and why
- Link issues: Reference related issues in your PR description (e.g., "Fixes #123")
- Keep PRs focused: One feature or fix per PR makes review easier
PyHamcrest uses automated releases via git tags.
-
Ensure all PRs for the release are merged to
main -
Run the release script:
./release.sh V2.2.0This script:
- Creates a git tag (e.g.,
V2.2.0) - Runs
towncrier buildto generate the changelog from fragments inchangelog.d/ - Re-tags to include the changelog changes
- Prompts you to push the tag
- Push the tag to trigger the release:
git push origin --tags "V2.2.0"- GitHub Actions automatically:
- Builds the package (wheel and sdist)
- Publishes to PyPI using trusted publishing
- Creates a GitHub release
- Format:
V{major}.{minor}.{patch}(e.g.,V2.1.0) - Version is automatically derived from git tags using hatch-vcs
- No manual version bumping needed in code
If you have questions or need help:
Thank you for contributing! 🎉