Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Migrate dependency management to pyproject.toml with uv - #172

Draft
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171
Draft

Migrate dependency management to pyproject.toml with uv#172
matrixise wants to merge 6 commits into
masterfrom
feature/migrate-to-uv-171

Conversation

@matrixise

@matrixisematrixise commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

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

  • Replacedrequirements/main.in, requirements/dev.in, requirements/production.inpyproject.toml
  • Generateduv.lock as universal lock file (102 packages resolved)
  • Auto-generaterequirements.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
@matrixisematrixise changed the title 🔧 Standardize on uv for dependency managementMigrate dependency management to pyproject.toml with uvDec 23, 2025
matrixiseand 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
@matrixisematrixise self-assigned this Dec 24, 2025
@matrixise
matrixiseforce-pushed the feature/migrate-to-uv-171 branch from 567a21b to 7ff27a6CompareDecember 24, 2025 11:37
Comment on lines +12 to 13
- name: Set Up Python 3.13
uses: actions/setup-python@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

Comment threadrequirements/main.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these exports still necessary? I tried to check how they are being used after uv migration but I couldn't catch the usecase.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ulgens,
I haven't checked if Heroku supports uv yet, but the main idea was to keep full compatibility with Heroku and the requirements files. This ensures the deployment pipeline continues to work as expected without any changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you.

Checking Heroku docs now and it seems they already have the uv support in place: https://devcenter.heroku.com/changelog-items/3238 I also checked

Sign up for freeto 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

@matrixise@ulgens