that initial commit
This commit is contained in:
552
docs/decisions/ADR-006-python-virtual-environment-uv.md
Normal file
552
docs/decisions/ADR-006-python-virtual-environment-uv.md
Normal file
@@ -0,0 +1,552 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user