Contributing to django-countries¶
Thank you for considering contributing to django-countries!
π Contributing Translations¶
Want to help translate country names? Visit our Transifex project to contribute translations. No coding required!
Country names are translated using Django's standard i18n system. All translation work is done through Transifex, making it easy for anyone to contribute translations in their language.
Development Setup¶
The rest of this guide covers code contributions. If you're contributing translations, head to Transifex instead!
This project uses modern Python tooling:
- uv - Fast Python package manager and runner
- just - Command runner for common development tasks
- ruff - Fast all-in-one linter and formatter
Prerequisites¶
-
Install uv (Python package manager)
Or see uv installation docs -
Install just (command runner)
Quick Start¶
# Set up development environment
uv sync
# Run all tests and coverage
just test
# Run all checks (format, lint, type, docs, tests)
just check
Available Commands¶
See all commands:
Testing¶
# Run all test environments (Python 3.8-3.13, Django 3.2-5.2)
just test
# Quick test with current Python (no coverage matrix)
just test quick
# Run specific environment
just test [latest|previous|legacy|latest-pyuca|latest-noi18n]
# Examples:
just test latest # Latest Django/DRF with Python 3.13
just test previous # Django 4.2 with Python 3.10
just test legacy # Django 3.2 with Python 3.8
# Run specific environment with custom Python version
just test [latest|previous|legacy|latest-pyuca|latest-noi18n] [3.8-3.13]
# Examples:
just test latest 3.12 # Latest Django with Python 3.12
just test previous 3.9 # Django 4.2 with Python 3.9
Test environments:
- legacy: Python 3.8 + Django 3.2 + DRF 3.11
- previous: Python 3.10 + Django 4.2 + DRF 3.14
- latest: Python 3.13 + Django 5.2 + DRF 3.15
- latest-pyuca: Latest + pyuca (Unicode collation)
- latest-noi18n: Latest + i18n disabled
Coverage is automatically generated when running just test.
Code Quality¶
The just check command runs all quality checks (formatting, linting, type checking, docs, and tests).
For individual checks, you can run the tools directly:
# Format code (import sorting + formatting)
uv run ruff check --select I --fix django_countries
uv run ruff format django_countries
# Check formatting without changes
uv run ruff check --select I django_countries
uv run ruff format --check django_countries
# Run linters
uv run ruff check django_countries
uv run bandit -r django_countries -x tests
# Type checking
uv run mypy django_countries
Development Workflow¶
- Make changes to the code
- Run tests:
just test quick(fastest) orjust test latest(single env) orjust test(full matrix) - Check everything:
just check(runs all checks) - Commit your changes
Pre-commit Hooks¶
Optional but recommended:
# Install pre-commit hooks
uvx pre-commit install
# Run hooks manually on all files
uvx pre-commit run --all-files
Testing¶
Tests are in django_countries/tests/:
- test_fields.py - CountryField model field tests
- test_countries.py - Countries class tests
- test_drf.py - Django REST Framework integration
- test_admin_filters.py - Admin filter tests
- test_widgets.py - Widget rendering tests
- test_tags.py - Template tag tests
- graphql/ - GraphQL integration tests
Coverage Requirements¶
- Tests: 100% coverage required
- Source code: 90% coverage required
Coverage is generated automatically when running just test. View the report by opening htmlcov/index.html in your browser.
Code Style¶
This project uses:
- ruff for linting, import sorting, and formatting
- mypy for type checking
- bandit for security scanning
The pre-commit hooks will automatically enforce style. You can also run just check to verify all style requirements.
Migration from Tox¶
If you previously used tox, here's the command mapping:
| Old (tox) | New (uv/just) |
|---|---|
tox |
just test |
tox -e py311-latest |
just test latest 3.11 |
tox -e mypy |
uv run mypy django_countries |
tox -e bandit |
uv run bandit -r django_countries -x tests |
tox -e readme |
uv run --group docs mkdocs build --strict |
black . |
uv run ruff format django_countries |
Releasing (for Maintainers)¶
Prerequisites¶
Before releasing, ensure you have:
- Your PyPI credentials in your keyring and the keyring tool installed (see setup below)
- The Transifex CLI installed (see installation instructions below)
πΊοΈ Updating Country Data¶
Country data should be manually updated from the official ISO 3166-1 Online Browsing Platform (OBP) when changes occur:
- Visit: https://www.iso.org/obp/ui/
- Click the 'Country Codes' radio button
- Click the search button (π)
- Change 'Results per page' to 300
- Select and copy the table data
- Paste into a spreadsheet (LibreOffice Calc, Excel, etc.)
- Verify columns: Country Name, Alpha-2, Alpha-3, Numeric
- Delete any extra columns (like French names)
- Delete the header row
- Save as
django_countries/iso3166-1.csv - Run:
uv run --group dev python django_countries/data.pyto regeneratedata.py
The official OBP data uses specific formatting patterns documented in ISO 3166-1 Country Name Formatting.
Quick Release (Recommended)¶
The just deploy [patch|minor|major] command handles the entire release process (bump type required):
# For a patch release (bug fixes: 7.7.0 -> 7.7.1)
just deploy patch
# For a minor release (new features: 7.7.0 -> 7.8.0)
just deploy minor
# For a major release (breaking changes: 7.7.0 -> 8.0.0)
just deploy major
This will:
1. Check for uncommitted changes (must have clean working directory)
2. Pull latest changes from git
3. Pull and compile translations from Transifex
4. Commit translation updates (if any)
5. Preview changelog to verify fragments exist
6. Bump version in pyproject.toml
7. Run pre-commit checks on version bump
8. Build package to verify everything works
9. Build changelog from fragments and commit atomically
10. Create and push git tag
11. Build final package and publish to PyPI
12. Deploy documentation to GitHub Pages
Note: Add changelog entries to changes/ directory before releasing. See changes/README.md for details.
Choosing the Right Release Type¶
This project follows Semantic Versioning:
- Patch (X.Y.Z): Bug fixes, translations, flag updates, documentation fixes
- Minor (X.Y.0): New features, new Django/Python/DRF support, country name changes, performance improvements
- Major (X.0.0): Breaking changes, dropping Python/Django support, API changes, removing deprecated features
Key Rule: Adding version support = minor. Dropping version support = major.
After the release, remember to bump to the next development version:
uv version --bump minor
# Manually edit pyproject.toml to change version from X.Y.0 to X.Y.dev0
git add pyproject.toml
git commit -m "Back to development: X.Y.dev0"
git push
Manual Release¶
If you prefer manual control, you can do each step individually:
1. Prepare translations
2. Bump version
3. Build changelog
uv run --group dev towncrier build --version $(uv version --short) --date "$(date '+%-d %B %Y')" --yes
4. Commit and tag
git add pyproject.toml CHANGES.md changes/
git commit -m "Preparing release $(uv version --short)"
git tag -a v$(uv version --short) -m "Release v$(uv version --short)"
git push --tags
git push
5. Build and publish
Setting Up PyPI Credentials¶
Install keyring (used by uv for publishing) and set your credentials:
Next, add these environment variables (e.g., in your ~/.bashrc or ~/.zshrc):
Installing Transifex CLI¶
The Transifex CLI is required for pulling translations before a release:
# Install using the official installer
curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
See the Transifex CLI documentation for alternative installation methods.
Getting Help¶
- Check
just --listfor available commands - See the documentation for project information
- Open an issue on GitHub for questions or problems
Pull Requests¶
- Fork the repository
- Create a feature branch
- Make your changes
- Add a changelog entry in
changes/(seechanges/README.md) - Run
just checkto ensure all checks pass - Submit a pull request
All PRs must pass CI checks (formatting, linting, type checking, tests).
Adding Changelog Entries¶
For changes that should appear in the release notes, create a file in the changes/ directory:
# With issue/PR number
echo "Your change description" > changes/123.bugfix.rst
# Without issue/PR (prefix with +)
echo "Your change description" > changes/+20250104.misc.rst
Types: feature, bugfix, doc, removal, misc
See changes/README.md for full details.