Skip to content

Installing Python Development Dependencies with uv ​

Managing both production and development dependencies is essential for Python development workflows. When using uv (Astral's fast Python package installer), development dependencies require special handling through dependency groups.

Problem Statement ​

When managing a Python project with uv, developers encounter these challenges:

  1. Production dependencies installed via uv pip compile or uv pip sync don't include dev dependencies
  2. The [tool.uv] section in pyproject.toml doesn't automatically install development dependencies
  3. Running direct commands like uv sync might fail with layout errors:
    error: Multiple top-level packages discovered in a flat-layout

Solution Overview ​

The optimal approach combines these techniques:

  1. Use **dependency groups (PEP 735)** for dev dependencies
  2. Install using uv sync which handles dependency groups automatically
  3. Fix flat-layout errors with setuptools configuration
  4. Pin Python versions for consistent environments

1. Configuring Dependency Groups ​

Replace tool.uv.dev-dependencies with dependency-groups in your pyproject.toml:

toml
[project]
name = "my-project"
dependencies = [
  "django",
]

[build-system]
requires = ["setuptools", "uv"]
build-backend = "setuptools.build_meta"

# Modern dependency groups (uv >= 0.4.0)
[dependency-groups]
dev = [
  "factory-boy",
  "pytest"
]

[tool.setuptools]  # Prevents flat-layout errors
py-modules = []

PRO TIP

Run uv add --dev factory-boy to automatically add dependencies to the dev group and update pyproject.toml

2. Installing All Dependencies ​

Install both production and development dependencies with:

bash
# Create virtual environment
uv venv

# Install all dependencies (including dev group)
uv sync

3. Resolving Common Errors ​

Problem: Multiple top-level packages discovered in a flat-layout
Solution: Add setuptools configuration to pyproject.toml:

toml
[tool.setuptools]
py-modules = []  # Explicitly declare no top-level modules

4. Pinning Python Version ​

For consistent environments:

bash
uv python pin 3.10  # Creates .python-version file

Key Workflow Commands ​

CommandPurpose
uv add --dev packageAdd to dev dependency group
uv syncInstall all dependencies (default includes 'dev')
uv sync --no-devInstall only production dependencies
uv python pin 3.10Pin project Python version

Advanced Configuration ​

Customize default groups in pyproject.toml:

toml
[tool.uv]
default-groups = ["dev", "test"]  # Install these groups by default

Understanding Dependency Types ​

TypeLocationPublishedInstall Command
Production[project].dependenciesYesuv sync
Optional (Extras)[project.optional-dependencies]Yesuv sync --with extra_name
Development[dependency-groups]Nouv sync (default)

WARNING

Avoid the obsolete tool.uv.dev-dependencies approach - it's been replaced by dependency groups

Complete Setup Example ​

  1. Initialize your project:
bash
uv init
uv venv
  1. Add dependencies:
bash
uv add django           # Production dependency
uv add --dev pytest     # Dev dependency
  1. Install everything:
bash
uv sync
source .venv/bin/activate

Conclusion ​

  1. Use [dependency-groups] for development dependencies
  2. Install all dependencies with uv sync
  3. Fix layout errors with [tool.setuptools]
  4. Manage dependencies through uv add --dev

This workflow keeps development dependencies separate from production while ensuring a consistent installation process.