Skip to content

Conversation

@matrixise
Copy link
Contributor

@matrixise matrixise commented Dec 23, 2025

Description

Complete migration from the legacy pip-tools workflow using requirements/*.in files to a modern Python packaging approach using pyproject.toml with uv for dependency management.

This migration consolidates all dependency declarations into a single source of truth (pyproject.toml) following PEP 621 (project metadata) and PEP 735 (dependency groups) standards.

Type of Change

  • Refactoring
  • Documentation update
  • Bug fix
  • New feature

Key Changes

Structure

  • Replaced requirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generated uv.lock as universal lock file (102 packages resolved)
  • Auto-generate requirements.txt for Heroku deployment compatibility
  • Centralized all tool configurations (ruff, coverage, isort) in pyproject.toml
  • Using Hatchling as build backend

New Workflow

# Update dependencies
uv lock

# Install dependencies (development)
uv sync

# Install dependencies (production)
uv sync --no-dev --group production

# Export for Heroku
task dependencies:export

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

Files Modified

  • pyproject.toml - New single source of truth
  • uv.lock - Universal lock file
  • Taskfile.yaml - Updated dependency management tasks
  • toast.yml - Updated Docker-based dependency tasks
  • Dockerfile - Use uv sync instead of pip install
  • .github/workflows/test.yml - Updated CI to use uv
  • CLAUDE.md, README.md, DEVELOPMENT.md, CONTRIBUTING.md - Updated documentation

Files Removed

  • requirements/main.in, requirements/dev.in, requirements/production.in
  • requirements/main.txt, requirements/dev.txt, requirements/production.txt
  • requirements/ directory (now empty)
  • pythonie/setup.py (replaced by pyproject.toml)

Benefits

  1. Single source of truth - All dependencies in pyproject.toml
  2. Faster resolution - uv is 10-100x faster than pip
  3. Modern standards - PEP 621 + PEP 735 (approved Oct 2024)
  4. Centralized config - All tool settings in one file
  5. Better reproducibility - Universal lock file with hashes
  6. Simplified commands - One command to install instead of three

How to Test

Local Setup

# Clean environment
rm -rf .venv pythonie-venv

# Install with new system
uv sync

# Run tests
python pythonie/manage.py test pythonie --settings=pythonie.settings.tests --verbosity=2

Docker Setup

# Rebuild Docker image
task docker:build

# Run tests in Docker
task tests

Expected Results

  • ✅ All dependencies installed successfully
  • ✅ All 33 tests pass
  • ✅ requirements.txt generated with correct header
  • ✅ Development workflow unchanged from user perspective

Testing Performed

  • ✅ Clean installation with `uv sync`
  • ✅ All 33 tests pass (ran in 0.156s)
  • ✅ Generated `requirements.txt` for Heroku with auto-generated header
  • ✅ Verified all dependencies resolved correctly (102 packages)

Checklist

  • Code follows project style guidelines
  • Tests pass locally (`uv sync` + full test suite)
  • New tests added (N/A - infrastructure change)
  • Documentation updated (CLAUDE.md, README.md, DEVELOPMENT.md, CONTRIBUTING.md)
  • Backward compatibility maintained (requirements.txt still generated for Heroku)
  • All old dependency files removed
  • uv.lock committed to version control

Migration Impact

Developers

  • Must run `uv sync` instead of `pip install -r requirements.txt`
  • New commands via Taskfile (but similar to before)

CI/CD

  • GitHub Actions updated to use `uv sync`
  • All tests passing with new setup

Deployment (Heroku)

  • No impact - still uses `requirements.txt` (auto-generated)
  • Deployment process unchanged

References


Note: This is a significant infrastructure change, but maintains full backward compatibility for deployment while modernizing the development workflow.

Update all documentation and scripts to use `uv` instead of `pip` for installing dependencies. This provides significant performance improvements and better dependency resolution.

Changes:
- Update CLAUDE.md local development setup instructions
- Update README.md installation steps
- Update DEVELOPMENT.md dependency installation
- Update CONTRIBUTING.md setup instructions
- Update vagrant/provision.sh to use uv
- Add uv 0.9.18 to .tool-versions

Note: Dockerfile and GitHub Actions workflows already use uv.

Refs #171
…ect.toml

Complete migration from pip-tools workflow to modern uv-based dependency management:

- Replace requirements/main.in, dev.in, production.in with pyproject.toml
- Use PEP 735 dependency-groups for dev and production dependencies
- Generate uv.lock as universal lock file (102 packages)
- Auto-generate requirements.txt for Heroku compatibility
- Centralize tool configurations (ruff, coverage, isort) in pyproject.toml
- Use Hatchling as build backend
- Update all tooling (Taskfile, toast.yml, Dockerfile, CI/CD)
- Update documentation (CLAUDE.md, README.md, DEVELOPMENT.md, CONTRIBUTING.md)

New workflow:
- `uv lock` - Update lock file
- `uv sync` - Install dependencies
- `task dependencies:export` - Generate requirements.txt

Benefits:
- Single source of truth (pyproject.toml)
- Faster dependency resolution with uv
- Modern Python packaging standards (PEP 621, PEP 735)
- Simplified dependency management commands

Fixes #171
@matrixise matrixise changed the title 🔧 Standardize on uv for dependency management Migrate dependency management to pyproject.toml with uv Dec 23, 2025
matrixise and others added 4 commits December 23, 2025 21:22
The tests were failing because uv sync creates a virtual environment
but the test command was using the system Python. Using 'uv run'
ensures the tests run in the correct virtual environment with all
dependencies installed.
Django 6.0 was inadvertently installed due to missing version
constraints in pyproject.toml. This pins Django to 5.2.x series
(latest: 5.2.9) and Wagtail to 7.2.x for compatibility.

Changes:
- pyproject.toml: Add Django>=5.2.0,<5.3 constraint
- pyproject.toml: Add wagtail>=7.2.0,<7.3 constraint
- uv.lock: Regenerated with Django 5.2.9
- requirements.txt: Regenerated with Django 5.2.9
- requirements-dev.txt: Regenerated with Django 5.2.9

All 33 tests pass with Django 5.2.9.
…ibility

- Create requirements/main.txt with base dependencies (no dev, no production groups)
- Create requirements/production.txt with production-specific dependencies (psycopg)
- Update requirements.txt to reference both files (-r requirements/main.txt -r requirements/production.txt)

This maintains Heroku compatibility while using the modern pyproject.toml + uv workflow.
The requirements files are auto-generated from uv.lock using:
- uv export --no-dev --no-group production -o requirements/main.txt
- uv export --only-group production -o requirements/production.txt

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add README.md to COPY command (required by Hatchling build backend)
- Add --no-install-project flag to uv sync to install only dependencies
  without installing the pythonie package itself at this stage

This fixes the Docker build errors:
- "OSError: Readme file does not exist: README.md"
- "ValueError: Unable to determine which files to ship inside the wheel"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@matrixise matrixise marked this pull request as draft December 23, 2025 21:14
@matrixise matrixise self-assigned this Dec 24, 2025
@matrixise matrixise force-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6 Compare December 24, 2025 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔧 Migrate from pip to uv for dependency management

2 participants