Migration from Poetry to uv#
Added in version 2.0.0: This document describes the migration of the NexusLIMS project from Poetry to uv for dependency management and package installation. This information is primarily relevant for developers who were familiar with the previous Poetry-based workflow.
Why the Change?#
NexusLIMS migrated from Poetry to uv to leverage several key advantages:
Performance - uv is significantly faster than Poetry for dependency resolution and installation (often 10-100x faster)
Standard Compliance - Uses standard Python packaging formats (PEP 621) rather than Poetry-specific formats
Caching - More efficient caching mechanisms reduce redundant downloads and installations
Python Version Management - Built-in support for managing Python versions eliminates the need for separate tools like pyenv
Tool Management - Can manage Python-based tools globally or per-project
Active Development - Rapidly evolving project with frequent improvements and bug fixes
Simplified CI/CD - Faster CI/CD pipelines with better caching and simpler configuration
What Changed#
Files Removed#
poetry.lock- Poetry lock file (replaced byuv.lock)tox.ini- Tox configuration (simplified development experience by using uv directly)Poetry-specific configuration sections in
pyproject.toml
Files Added#
uv.lock- uv lock file with resolved dependencies and hashes.python-version- Specifies required Python version(s) for the project
Files Modified#
pyproject.toml- Converted from Poetry format to standard Python packaging format (PEP 621)README.md- Updated installation and development instructionsCI/CD configuration files - Updated to use uv instead of Poetry
Shell scripts - Updated to use
uv runinstead ofpoetry run
pyproject.toml Changes#
The project configuration was converted from Poetry’s custom format to the standard Python packaging format defined in PEP 621.
Before (Poetry format)#
[tool.poetry]
name = "nexusLIMS"
version = "1.4.3"
description = "Electron Microscopy Nexus LIMS project"
authors = ["Author Name <author@example.com>"]
[tool.poetry.dependencies]
python = ">=3.8.1,<3.11"
lxml = "^4.9.2"
requests = "^2.28.1"
# ... other dependencies
[tool.poetry.dev-dependencies]
pytest = "^7.2"
coverage = "^7.0.0"
# ... other dev dependencies
After (Standard Python packaging)#
[project]
name = "nexusLIMS"
version = "2.0.0a4"
description = "Electron Microscopy Nexus LIMS project (Datasophos fork)"
authors = [
{name = "Joshua Taillon", email = "josh@datasophos.co"}
]
requires-python = ">=3.11,<3.13"
dependencies = [
"lxml>=4.9.2,<5.0.0",
"requests>=2.28.1,<3.0.0",
# ... other dependencies
]
[dependency-groups]
dev = [
"pytest>=7.2",
"coverage>=7.0.0",
# ... other dev dependencies
]
[project.scripts]
nexuslims = "nexusLIMS.cli.main:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Key differences:
[tool.poetry]→[project](standard format)[tool.poetry.dependencies]→dependencies = [...](list format)[tool.poetry.dev-dependencies]→[dependency-groups](uv-specific but standard-compatible)Version constraints use explicit ranges instead of Poetry’s caret (
^) syntax[project.scripts]defines command-line entry pointshatchlingis used as the build backend instead of Poetry
Command Reference#
This table shows the equivalent uv commands for common Poetry operations:
Poetry Command |
uv Equivalent |
Description |
|---|---|---|
|
|
Install dependencies |
|
|
Install with dev dependencies (included by default) |
|
|
Install without dev dependencies |
|
|
Run Python script |
|
|
Run tests |
|
|
Add dependency |
|
|
Add dev dependency |
|
|
Remove dependency |
|
|
Activate virtual environment |
|
|
List installed packages |
|
|
Show dependency tree |
|
|
Update lock file |
|
|
Update all dependencies |
|
|
Update specific package |
|
|
Show Python environment info |
|
|
Verify dependencies are in sync |
Development Workflow#
Setting Up Development Environment#
For developers who previously used Poetry:
# Remove old Poetry virtual environment (optional but recommended)
rm -rf .venv
# Remove Poetry lock file if it exists
rm -f poetry.lock
# Install dependencies with uv
uv sync
Running Tests#
# Run all tests with coverage and matplotlib comparison (recommended)
./scripts/run_tests.sh
# Run all unit tests with mpl comparison
uv run pytest --mpl --mpl-baseline-path=tests/unit/files/figs tests/unit
# Run all integration tests (uses Docker to mock external services)
uv run pytest tests/integration
# Run specific test file with mpl comparison
uv run pytest --mpl --mpl-baseline-path=tests/unit/files/figs tests/unit/test_extractors/test_quanta_tif.py
# Run specific test
uv run pytest tests/unit/test_extractors/test_quanta_tif.py::TestQuantaTifExtractor::test_extraction
# Run with HTML coverage report
uv run pytest --cov=nexusLIMS --cov-report=html tests/unit
Running Linting and Formatting#
# Run all linting checks
./scripts/run_lint.sh
# Or run ruff directly
uv run ruff check nexusLIMS tests
# Auto-fix issues
uv run ruff check --fix nexusLIMS tests
# Format code
uv run ruff format nexusLIMS tests
Building Documentation#
# Build documentation
./scripts/build_docs.sh
# Watch changes to documentation files and rebuild automatically
# (this is useful when working interactively on the docs)
./scripts/build_docs.sh --watch
# Or run Sphinx directly
uv run sphinx-build -b html docs _build
Running the Record Builder#
# Using the CLI entry point
uv run nexuslims build-records
# Or using the module directly
uv run python -m nexusLIMS.cli.process_records
# Dry run mode
uv run nexuslims build-records -n
# Verbose mode
uv run nexuslims build-records -vv
Managing Dependencies#
Adding Dependencies#
# Add a production dependency
uv add requests
# Add a specific version
uv add "requests>=2.28.0,<3.0.0"
# Add a development dependency
uv add --dev pytest-mock
Removing Dependencies#
# Remove a dependency
uv remove package-name
# This will update both pyproject.toml and uv.lock
Updating Dependencies#
# Update all dependencies to latest compatible versions
uv lock --upgrade
# Update a specific package
uv lock --upgrade-package requests
# Update multiple packages
uv lock --upgrade-package requests --upgrade-package lxml
# After updating, sync the environment
uv sync
Python Version Management#
Unlike Poetry, uv can automatically manage Python versions:
# List available Python versions
uv python list
# Install a specific Python version
uv python install 3.11
# Use a specific Python version for this project
uv python pin 3.11
# This creates/updates .python-version file
The .python-version file in the project root specifies the required Python version(s). uv will automatically use or download the appropriate Python version when you run commands.
Virtual Environment Management#
uv automatically manages virtual environments in the .venv directory:
# Create/update virtual environment (done automatically by uv sync)
uv venv
# Activate the virtual environment manually (if needed)
source .venv/bin/activate # Unix/macOS
# Deactivate
deactivate
# Remove virtual environment
rm -rf .venv
Benefits of uv’s Approach#
Local to project: The
.venvdirectory is in the project root, not in a global cacheAutomatic creation: uv creates the venv automatically when needed
Fast: Virtual environment creation is nearly instantaneous
No configuration needed: Works out of the box without additional setup
CI/CD Integration#
The project’s CI/CD configuration has been updated to use uv:
GitHub Actions Example#
- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- name: Install dependencies
run: uv sync
- name: Run unit tests
run: |
uv run pytest tests/unit/ --cov=nexusLIMS \
--cov-report html:tests/coverage \
--cov-report term-missing \
--cov-report=xml \
--mpl --mpl-baseline-path=tests/unit/files/figs
Benefits in CI/CD:
Faster installation: uv’s speed significantly reduces CI/CD run times
Better caching: More efficient layer caching in Docker builds
Reproducible builds: Lock file ensures exact dependency versions
Parallel installations: uv can install packages in parallel
Troubleshooting#
Lock File Conflicts#
If you encounter issues with the lock file after pulling changes:
# Regenerate lock file
uv lock
# Or force a complete rebuild
rm uv.lock
uv lock
Virtual Environment Issues#
If the virtual environment seems corrupted or out of sync:
# Remove and recreate
rm -rf .venv
uv sync
Dependency Resolution Conflicts#
If uv cannot resolve dependencies:
# Try with verbose output to see the conflict
uv sync --verbose
# Check for conflicting requirements
uv pip tree
# If needed, upgrade problematic packages
uv lock --upgrade-package problematic-package
Missing Commands After Installation#
If CLI commands aren’t available after installation:
# Ensure you're using uv run
uv run nexuslims build-records
# Or activate the virtual environment
source .venv/bin/activate
nexuslims build-records
Python Version Issues#
If the wrong Python version is being used:
# Check current Python
uv run python --version
# Pin to correct version
uv python pin 3.11
# Recreate environment
rm -rf .venv
uv sync
Comparison with Poetry#
Feature Comparison#
Feature |
Poetry |
uv |
|---|---|---|
Speed |
Moderate |
Very fast (10-100x faster) |
Lock file format |
TOML |
JSON (more efficient parsing) |
Python version management |
Via external tools (pyenv) |
Built-in |
Virtual environment location |
Configurable global cache |
Local |
Configuration format |
Poetry-specific |
Standard PEP 621 |
Parallel installation |
Limited |
Full parallel support |
Tool installation |
Via |
Global tool management |
Caching |
Good |
Excellent |
Ecosystem maturity |
Mature (2018) |
Newer but stable (2023) |