553 lines
16 KiB
Markdown
553 lines
16 KiB
Markdown
# ADR-006: Python Virtual Environment Management with uv
|
|
|
|
## Status
|
|
Accepted
|
|
|
|
## Context
|
|
StarPunk is a Python-based web application that requires dependency management and virtual environment isolation. Developer agents (AI assistants like Claude Code) need clear, unambiguous standards for:
|
|
|
|
- Creating and managing Python virtual environments
|
|
- Installing and tracking dependencies
|
|
- Ensuring reproducible development environments
|
|
- Avoiding common pitfalls (polluting global Python, dependency conflicts)
|
|
- Maintaining consistency across development and deployment
|
|
|
|
Traditional tools (pip, venv, virtualenv, poetry, pipenv) have various limitations:
|
|
- **pip + venv**: Slow dependency resolution, manual requirements.txt management
|
|
- **poetry**: Complex configuration, slow, dependency lock issues
|
|
- **pipenv**: Abandoned maintenance, slow performance
|
|
- **conda**: Heavyweight, non-standard for web development
|
|
|
|
We need a tool that is fast, simple, and provides excellent developer experience while maintaining compatibility with standard Python packaging.
|
|
|
|
## Decision
|
|
Use **uv** for all Python virtual environment and dependency management in StarPunk.
|
|
|
|
uv will be the standard tool for:
|
|
- Creating virtual environments
|
|
- Installing dependencies
|
|
- Managing requirements
|
|
- Running Python commands in the virtual environment
|
|
- Synchronizing dependencies
|
|
|
|
## Rationale
|
|
|
|
### Simplicity Score: 10/10
|
|
- Single tool for all environment management
|
|
- Simple command syntax (uv venv, uv pip install, uv run)
|
|
- Drop-in replacement for pip and virtualenv
|
|
- No complex configuration files
|
|
- Works with standard requirements.txt
|
|
- Written in Rust, installed as single binary
|
|
|
|
### Performance Score: 10/10
|
|
- 10-100x faster than pip for dependency resolution
|
|
- Parallel downloads and installations
|
|
- Efficient caching mechanism
|
|
- Near-instant virtual environment creation
|
|
- Minimal overhead for running commands
|
|
|
|
### Fitness Score: 9/10
|
|
- Perfect for small to medium Python projects
|
|
- Excellent for single-developer projects
|
|
- Works with standard Python packaging (PEP 517/518)
|
|
- Compatible with requirements.txt workflow
|
|
- Supports editable installs for development
|
|
- Works seamlessly with Flask and all our dependencies
|
|
|
|
### Maintenance Score: 9/10
|
|
- Actively developed by Astral (creators of ruff)
|
|
- Strong community adoption
|
|
- Excellent documentation
|
|
- Regular updates and improvements
|
|
- Modern codebase (Rust)
|
|
- Backed by funding and commercial support
|
|
|
|
### Standards Compliance: Pass
|
|
- Full compatibility with pip
|
|
- Works with PyPI and all standard package indices
|
|
- Supports PEP 440 version specifiers
|
|
- Compatible with requirements.txt format
|
|
- Works with standard Python virtual environments
|
|
- No proprietary lock files (uses standard formats)
|
|
|
|
## Implementation Details
|
|
|
|
### 1. Installation Standards
|
|
|
|
#### System-Level uv Installation
|
|
Developer agents MUST ensure uv is installed before creating environments:
|
|
|
|
```bash
|
|
# Check if uv is installed
|
|
which uv
|
|
|
|
# If not installed, install via pip (fallback)
|
|
pip install uv
|
|
|
|
# Or install via official installer (preferred on Linux/macOS)
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
```
|
|
|
|
#### Verification
|
|
```bash
|
|
# Verify uv installation
|
|
uv --version
|
|
# Expected output: uv 0.x.x (or newer)
|
|
```
|
|
|
|
### 2. Virtual Environment Creation Standards
|
|
|
|
#### Location and Naming
|
|
- **Standard location**: `/home/phil/Projects/starpunk/.venv`
|
|
- **Name**: Always use `.venv` (hidden directory)
|
|
- **DO NOT** use: `venv`, `env`, `virtualenv`, or custom names
|
|
|
|
#### Creation Command
|
|
```bash
|
|
# Create virtual environment with uv
|
|
cd /home/phil/Projects/starpunk
|
|
uv venv .venv
|
|
|
|
# Specify Python version (recommended)
|
|
uv venv .venv --python 3.11
|
|
```
|
|
|
|
#### Post-Creation Verification
|
|
```bash
|
|
# Verify .venv directory exists
|
|
ls -la /home/phil/Projects/starpunk/.venv
|
|
|
|
# Verify Python executable
|
|
/home/phil/Projects/starpunk/.venv/bin/python --version
|
|
```
|
|
|
|
### 3. Dependency Installation Standards
|
|
|
|
#### Using requirements.txt (Primary Method)
|
|
```bash
|
|
# Install all dependencies from requirements.txt
|
|
uv pip install -r /home/phil/Projects/starpunk/requirements.txt
|
|
|
|
# Verify installation
|
|
uv pip list
|
|
```
|
|
|
|
#### Installing Individual Packages
|
|
```bash
|
|
# Install a single package
|
|
uv pip install flask==3.0.*
|
|
|
|
# Install multiple packages
|
|
uv pip install flask markdown feedgen
|
|
```
|
|
|
|
#### Development Dependencies
|
|
```bash
|
|
# Install dev dependencies (if requirements-dev.txt exists)
|
|
uv pip install -r /home/phil/Projects/starpunk/requirements-dev.txt
|
|
```
|
|
|
|
### 4. Running Commands in Virtual Environment
|
|
|
|
#### Using uv run (Recommended)
|
|
```bash
|
|
# Run Python script
|
|
uv run /home/phil/Projects/starpunk/.venv/bin/python script.py
|
|
|
|
# Run Flask development server
|
|
uv run /home/phil/Projects/starpunk/.venv/bin/flask run
|
|
|
|
# Run pytest
|
|
uv run /home/phil/Projects/starpunk/.venv/bin/pytest
|
|
|
|
# Run Python REPL
|
|
uv run /home/phil/Projects/starpunk/.venv/bin/python
|
|
```
|
|
|
|
#### Direct Execution (Alternative)
|
|
```bash
|
|
# Execute using absolute path to venv Python
|
|
/home/phil/Projects/starpunk/.venv/bin/python script.py
|
|
/home/phil/Projects/starpunk/.venv/bin/flask run
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest
|
|
```
|
|
|
|
### 5. Dependency Tracking Standards
|
|
|
|
#### Generating requirements.txt
|
|
```bash
|
|
# Freeze current environment to requirements.txt
|
|
uv pip freeze > /home/phil/Projects/starpunk/requirements.txt
|
|
|
|
# Freeze with sorted output for consistency
|
|
uv pip freeze | sort > /home/phil/Projects/starpunk/requirements.txt
|
|
```
|
|
|
|
#### Adding New Dependencies
|
|
When adding a new dependency:
|
|
1. Install the package: `uv pip install package-name`
|
|
2. Update requirements.txt: `uv pip freeze | sort > requirements.txt`
|
|
3. Verify installation: `uv pip list | grep package-name`
|
|
|
|
### 6. Environment Updates and Maintenance
|
|
|
|
#### Updating Dependencies
|
|
```bash
|
|
# Update a specific package
|
|
uv pip install --upgrade flask
|
|
|
|
# Update all packages (use with caution)
|
|
uv pip install --upgrade -r requirements.txt
|
|
|
|
# Regenerate requirements.txt after updates
|
|
uv pip freeze | sort > requirements.txt
|
|
```
|
|
|
|
#### Cleaning and Rebuilding
|
|
```bash
|
|
# Remove virtual environment
|
|
rm -rf /home/phil/Projects/starpunk/.venv
|
|
|
|
# Recreate from scratch
|
|
uv venv .venv --python 3.11
|
|
uv pip install -r requirements.txt
|
|
```
|
|
|
|
## Developer Agent Standards
|
|
|
|
### Critical Rules for AI Assistants
|
|
|
|
#### Rule 1: ALWAYS Check for Existing Virtual Environment
|
|
Before creating a new virtual environment, ALWAYS check:
|
|
|
|
```bash
|
|
# Check if .venv exists
|
|
if [ -d "/home/phil/Projects/starpunk/.venv" ]; then
|
|
echo "Virtual environment exists"
|
|
/home/phil/Projects/starpunk/.venv/bin/python --version
|
|
else
|
|
echo "Virtual environment does not exist"
|
|
fi
|
|
```
|
|
|
|
**NEVER** create a new virtual environment if one already exists without explicit user permission.
|
|
|
|
#### Rule 2: ALWAYS Use Absolute Paths
|
|
Agent threads reset cwd between bash calls. ALWAYS use absolute paths:
|
|
|
|
**CORRECT:**
|
|
```bash
|
|
uv venv /home/phil/Projects/starpunk/.venv
|
|
/home/phil/Projects/starpunk/.venv/bin/python script.py
|
|
uv pip install -r /home/phil/Projects/starpunk/requirements.txt
|
|
```
|
|
|
|
**INCORRECT:**
|
|
```bash
|
|
uv venv .venv # Relative path - WRONG
|
|
./venv/bin/python script.py # Relative path - WRONG
|
|
uv pip install -r requirements.txt # Relative path - WRONG
|
|
```
|
|
|
|
#### Rule 3: Verify Before Executing
|
|
Before running Python commands, verify the virtual environment:
|
|
|
|
```bash
|
|
# Verification checklist
|
|
[ -d "/home/phil/Projects/starpunk/.venv" ] && echo "✓ venv exists" || echo "✗ venv missing"
|
|
[ -f "/home/phil/Projects/starpunk/.venv/bin/python" ] && echo "✓ Python exists" || echo "✗ Python missing"
|
|
/home/phil/Projects/starpunk/.venv/bin/python --version
|
|
```
|
|
|
|
#### Rule 4: Handle Errors Gracefully
|
|
If virtual environment operations fail:
|
|
|
|
1. **Check uv installation**: `which uv`
|
|
2. **Check Python version**: `python3 --version`
|
|
3. **Check disk space**: `df -h /home/phil/Projects/starpunk`
|
|
4. **Report specific error** to user with context
|
|
5. **DO NOT** silently continue with global Python
|
|
|
|
#### Rule 5: Never Modify Global Python
|
|
**NEVER** run these commands:
|
|
```bash
|
|
# FORBIDDEN - modifies global Python
|
|
pip install package
|
|
python3 -m pip install package
|
|
sudo pip install package
|
|
```
|
|
|
|
**ALWAYS** use virtual environment:
|
|
```bash
|
|
# CORRECT - uses virtual environment
|
|
uv pip install package
|
|
/home/phil/Projects/starpunk/.venv/bin/pip install package
|
|
```
|
|
|
|
#### Rule 6: Track Dependency Changes
|
|
After installing or removing packages:
|
|
|
|
1. Update requirements.txt: `uv pip freeze | sort > requirements.txt`
|
|
2. Verify changes: `git diff requirements.txt` (if applicable)
|
|
3. Inform user of changes made
|
|
|
|
### Standard Agent Workflow
|
|
|
|
#### Scenario 1: First-Time Setup
|
|
```bash
|
|
# 1. Check if venv exists
|
|
if [ ! -d "/home/phil/Projects/starpunk/.venv" ]; then
|
|
echo "Creating virtual environment..."
|
|
uv venv /home/phil/Projects/starpunk/.venv --python 3.11
|
|
fi
|
|
|
|
# 2. Verify creation
|
|
/home/phil/Projects/starpunk/.venv/bin/python --version
|
|
|
|
# 3. Install dependencies (if requirements.txt exists)
|
|
if [ -f "/home/phil/Projects/starpunk/requirements.txt" ]; then
|
|
uv pip install -r /home/phil/Projects/starpunk/requirements.txt
|
|
fi
|
|
|
|
# 4. Verify installation
|
|
uv pip list
|
|
```
|
|
|
|
#### Scenario 2: Running Development Server
|
|
```bash
|
|
# 1. Verify venv exists
|
|
[ -d "/home/phil/Projects/starpunk/.venv" ] || echo "ERROR: Virtual environment missing"
|
|
|
|
# 2. Verify Flask is installed
|
|
/home/phil/Projects/starpunk/.venv/bin/python -c "import flask; print(flask.__version__)"
|
|
|
|
# 3. Run Flask development server
|
|
/home/phil/Projects/starpunk/.venv/bin/flask --app /home/phil/Projects/starpunk/app.py run
|
|
```
|
|
|
|
#### Scenario 3: Adding New Dependency
|
|
```bash
|
|
# 1. Install package
|
|
uv pip install httpx
|
|
|
|
# 2. Verify installation
|
|
uv pip show httpx
|
|
|
|
# 3. Update requirements.txt
|
|
uv pip freeze | sort > /home/phil/Projects/starpunk/requirements.txt
|
|
|
|
# 4. Confirm to user
|
|
echo "Added httpx to project dependencies"
|
|
```
|
|
|
|
#### Scenario 4: Running Tests
|
|
```bash
|
|
# 1. Verify pytest is installed
|
|
/home/phil/Projects/starpunk/.venv/bin/python -c "import pytest; print(pytest.__version__)"
|
|
|
|
# 2. Run tests
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest /home/phil/Projects/starpunk/tests/
|
|
|
|
# 3. Run tests with coverage (if pytest-cov installed)
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest --cov=/home/phil/Projects/starpunk/src /home/phil/Projects/starpunk/tests/
|
|
```
|
|
|
|
## Project-Specific Standards
|
|
|
|
### Python Version Requirements
|
|
- **Minimum**: Python 3.11
|
|
- **Recommended**: Python 3.11 or 3.12
|
|
- **Rationale**: Modern Python features, improved performance, security updates
|
|
|
|
### Directory Structure
|
|
```
|
|
/home/phil/Projects/starpunk/
|
|
├── .venv/ # Virtual environment (NEVER commit)
|
|
├── requirements.txt # Production dependencies
|
|
├── requirements-dev.txt # Development dependencies (optional)
|
|
├── src/ # Application source code
|
|
├── tests/ # Test files
|
|
└── docs/ # Documentation
|
|
```
|
|
|
|
### .gitignore Requirements
|
|
The following MUST be in .gitignore:
|
|
```
|
|
# Virtual Environment
|
|
.venv/
|
|
venv/
|
|
env/
|
|
ENV/
|
|
|
|
# Python
|
|
__pycache__/
|
|
*.py[cod]
|
|
*$py.class
|
|
*.so
|
|
.Python
|
|
```
|
|
|
|
### Environment Variables
|
|
Use python-dotenv for configuration:
|
|
```bash
|
|
# .env file (NEVER commit to git)
|
|
FLASK_APP=app.py
|
|
FLASK_ENV=development
|
|
SECRET_KEY=your-secret-key
|
|
DATABASE_PATH=/home/phil/Projects/starpunk/data/starpunk.db
|
|
```
|
|
|
|
Load in application:
|
|
```python
|
|
from dotenv import load_dotenv
|
|
load_dotenv()
|
|
```
|
|
|
|
### Requirements.txt Format
|
|
Follow these conventions:
|
|
```
|
|
# Requirements.txt - StarPunk Dependencies
|
|
# Generated: 2025-11-18
|
|
|
|
# Web Framework
|
|
flask==3.0.*
|
|
|
|
# Content Processing
|
|
markdown==3.5.*
|
|
|
|
# Feed Generation
|
|
feedgen==1.0.*
|
|
|
|
# HTTP Client
|
|
httpx==0.27.*
|
|
|
|
# Configuration
|
|
python-dotenv==1.0.*
|
|
```
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
- **10-100x faster** dependency resolution and installation
|
|
- **Consistent environments** across development and deployment
|
|
- **Simple workflow** - one tool for all Python environment tasks
|
|
- **No activation required** - uv run handles environment automatically
|
|
- **Excellent caching** - faster subsequent installations
|
|
- **Standard compatibility** - works with all existing Python tools
|
|
- **Clear agent guidelines** - reduces errors in automated workflows
|
|
- **Isolated dependencies** - no conflicts with system Python
|
|
|
|
### Negative
|
|
- **Additional tool dependency** - requires uv installation
|
|
- **Less familiar** - newer tool, smaller community than pip
|
|
- **Rust dependency** - uv is written in Rust (but distributed as binary)
|
|
|
|
### Mitigation
|
|
- uv is easy to install (single binary, no compilation needed)
|
|
- uv is pip-compatible (drop-in replacement)
|
|
- Fallback to pip + venv is always possible
|
|
- Documentation and agent standards make adoption easy
|
|
- Active development and growing adoption reduce risk
|
|
|
|
### Trade-offs Accepted
|
|
- **uv vs poetry**: We chose simplicity over advanced features
|
|
- **uv vs pipenv**: We chose active maintenance and speed
|
|
- **uv vs pip**: We chose performance over ubiquity
|
|
- **Single tool complexity**: Better than managing multiple tools
|
|
|
|
## Verification Checklist
|
|
|
|
Before considering the environment correctly set up, verify:
|
|
|
|
- [ ] uv is installed and accessible: `which uv`
|
|
- [ ] Virtual environment exists: `ls -la /home/phil/Projects/starpunk/.venv`
|
|
- [ ] Python version is 3.11+: `/home/phil/Projects/starpunk/.venv/bin/python --version`
|
|
- [ ] Dependencies installed: `uv pip list` shows Flask, markdown, feedgen, httpx
|
|
- [ ] requirements.txt exists and is up to date
|
|
- [ ] .venv is in .gitignore
|
|
- [ ] Flask runs: `/home/phil/Projects/starpunk/.venv/bin/flask --version`
|
|
|
|
## Integration with Development Workflow
|
|
|
|
### Running Flask Application
|
|
```bash
|
|
# Development server
|
|
/home/phil/Projects/starpunk/.venv/bin/flask --app app.py run --debug
|
|
|
|
# Production server (using gunicorn)
|
|
/home/phil/Projects/starpunk/.venv/bin/gunicorn app:app
|
|
```
|
|
|
|
### Running Tests
|
|
```bash
|
|
# All tests
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest
|
|
|
|
# Specific test file
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest tests/test_api.py
|
|
|
|
# With coverage
|
|
/home/phil/Projects/starpunk/.venv/bin/pytest --cov=src tests/
|
|
```
|
|
|
|
### Code Quality Tools
|
|
```bash
|
|
# Format code with black
|
|
/home/phil/Projects/starpunk/.venv/bin/black src/
|
|
|
|
# Lint with flake8
|
|
/home/phil/Projects/starpunk/.venv/bin/flake8 src/
|
|
|
|
# Type checking with mypy (if added)
|
|
/home/phil/Projects/starpunk/.venv/bin/mypy src/
|
|
```
|
|
|
|
## Alternatives Considered
|
|
|
|
### pip + venv (Rejected)
|
|
- **Simplicity**: 8/10 - Standard Python tools, well-known
|
|
- **Performance**: 4/10 - Very slow dependency resolution
|
|
- **Fitness**: 7/10 - Works but painful for larger dependency trees
|
|
- **Maintenance**: 10/10 - Built into Python, always maintained
|
|
- **Verdict**: Too slow, poor developer experience, but acceptable fallback
|
|
|
|
### poetry (Rejected)
|
|
- **Simplicity**: 5/10 - Complex pyproject.toml, lock file management
|
|
- **Performance**: 5/10 - Slow dependency resolution
|
|
- **Fitness**: 6/10 - Overkill for simple project, lock files add complexity
|
|
- **Maintenance**: 7/10 - Maintained but has had reliability issues
|
|
- **Verdict**: Too complex for "minimal code" philosophy
|
|
|
|
### pipenv (Rejected)
|
|
- **Simplicity**: 6/10 - Simpler than poetry, but still adds abstraction
|
|
- **Performance**: 4/10 - Known performance issues
|
|
- **Fitness**: 5/10 - Previously recommended, now effectively abandoned
|
|
- **Maintenance**: 2/10 - Minimal maintenance, community has moved on
|
|
- **Verdict**: Dead project, poor performance
|
|
|
|
### conda (Rejected)
|
|
- **Simplicity**: 3/10 - Heavy, complex environment management
|
|
- **Performance**: 5/10 - Slower than uv, larger downloads
|
|
- **Fitness**: 2/10 - Designed for data science, not web development
|
|
- **Maintenance**: 9/10 - Well maintained, large ecosystem
|
|
- **Verdict**: Wrong tool for web application development
|
|
|
|
### PDM (Considered)
|
|
- **Simplicity**: 7/10 - Modern, PEP 582 support
|
|
- **Performance**: 8/10 - Fast, but not as fast as uv
|
|
- **Fitness**: 7/10 - Good for modern Python projects
|
|
- **Maintenance**: 8/10 - Actively maintained, growing community
|
|
- **Verdict**: Good alternative, but uv is faster and simpler
|
|
|
|
## References
|
|
- uv Documentation: https://docs.astral.sh/uv/
|
|
- uv GitHub: https://github.com/astral-sh/uv
|
|
- Python Virtual Environments: https://docs.python.org/3/library/venv.html
|
|
- PEP 405 (Python Virtual Environments): https://peps.python.org/pep-0405/
|
|
- requirements.txt format: https://pip.pypa.io/en/stable/reference/requirements-file-format/
|
|
- Astral (uv creators): https://astral.sh/
|
|
|
|
## Change Log
|
|
- 2025-11-18: Initial version - Established uv as standard tool for StarPunk Python environment management
|