Set up Python project with uv environment management and FastAPI stack. Project structure: - src/gondulf/ - Main application package - tests/ - Test suite directory - pyproject.toml - Project configuration with dependencies - README.md - Project documentation - uv.lock - Dependency lock file Dependencies configured: - FastAPI + Uvicorn for web framework - SQLAlchemy for database ORM - pytest + coverage for testing - ruff, black, mypy, flake8 for code quality - Development environment using uv direct execution model All project standards reviewed and implemented per: - /docs/standards/coding.md - /docs/standards/testing.md - /docs/standards/git.md - /docs/standards/development-environment.md - /docs/standards/versioning.md
7.5 KiB
Development Environment Standard
Overview
This document defines the standard development environment setup and workflow for the IndieAuth server project. We use uv for Python virtual environment management and package installation, following a direct execution model that eliminates the need for environment activation.
Prerequisites
System Requirements
- Python: 3.10 or higher
- Git: 2.25 or higher
- SQLite: 3.35 or higher (usually included with Python)
Installing uv
uv is available for all major platforms. Install using one of these methods:
Linux/macOS (recommended):
curl -LsSf https://astral.sh/uv/install.sh | sh
Using pip (alternative):
pip install uv
Using Homebrew (macOS):
brew install uv
After installation, verify:
uv --version
Project Setup
Initial Setup (First Time)
- Clone the repository:
git clone <repository-url> gondulf-indieauth
cd gondulf-indieauth
- Create virtual environment with uv:
uv venv
This creates a .venv directory in the project root.
- Install dependencies:
uv pip sync requirements.txt
Or if using pyproject.toml:
uv pip install -e .
Daily Development Workflow
IMPORTANT: You do NOT need to activate the virtual environment. Use uv run to execute commands within the environment context.
Using uv Direct Execution
Core Concept
Instead of activating/deactivating virtual environments, we use uv's direct execution commands. This approach:
- Eliminates activation state confusion
- Works consistently across all shells
- Makes commands explicit and clear
- Simplifies CI/CD pipelines
Common Development Commands
Running Python scripts:
# Instead of: python script.py
uv run python script.py
Starting the development server:
# Instead of: python -m uvicorn main:app --reload
uv run uvicorn main:app --reload
Running tests:
# Instead of: pytest
uv run pytest
# With coverage:
uv run pytest --cov=src --cov-report=term-missing
Interactive Python shell:
# Instead of: python
uv run python
Running linters and formatters:
# Instead of: ruff check .
uv run ruff check .
# Format code:
uv run ruff format .
Package Management
Installing packages:
# Instead of: pip install package
uv pip install package
# Install with extras:
uv pip install "package[extra]"
# Install development dependencies:
uv pip install -r requirements-dev.txt
Upgrading packages:
# Instead of: pip install --upgrade package
uv pip install --upgrade package
Listing installed packages:
# Instead of: pip list
uv pip list
Freezing dependencies:
# Instead of: pip freeze > requirements.txt
uv pip freeze > requirements.txt
Syncing with lock file:
# Ensures exact versions from lock file:
uv pip sync requirements.txt
IDE Configuration
VS Code
- Open VS Code settings (
.vscode/settings.json) - Configure Python interpreter:
{
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
"python.terminal.activateEnvironment": false
}
Setting activateEnvironment to false prevents VS Code from auto-activating, maintaining our direct execution model.
PyCharm
- Go to Settings → Project → Python Interpreter
- Click gear icon → Add
- Choose "Existing environment"
- Browse to:
<project-root>/.venv/bin/python - Uncheck "Activate virtualenv" in terminal settings
Other IDEs
Point the interpreter to .venv/bin/python and disable automatic activation if the option exists.
Common Workflows
Starting a New Feature
- Ensure dependencies are up to date:
uv pip sync requirements.txt
- Create feature branch:
git checkout -b feature/your-feature-name
- Run tests to ensure clean state:
uv run pytest
Adding a New Dependency
- Install the package:
uv pip install new-package
- Update requirements file:
uv pip freeze > requirements.txt
- Commit both changes:
git add requirements.txt
git commit -m "Add new-package to dependencies"
Running the Application
Development mode with auto-reload:
uv run uvicorn src.main:app --reload --host 127.0.0.1 --port 8000
Production-like mode:
uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
Running Tests
All tests:
uv run pytest
Specific test file:
uv run pytest tests/test_auth.py
With coverage report:
uv run pytest --cov=src --cov-report=html --cov-report=term-missing
Watch mode (requires pytest-watch):
uv run ptw
Code Quality Checks
Run all checks (before committing):
# Linting
uv run ruff check .
# Type checking
uv run mypy src
# Security scanning
uv run bandit -r src
# Test coverage
uv run pytest --cov=src --cov-report=term-missing
CI/CD Integration
uv commands work seamlessly in CI/CD pipelines without activation:
GitHub Actions example:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install uv
run: pip install uv
- name: Install dependencies
run: |
uv venv
uv pip sync requirements.txt
- name: Run tests
run: uv run pytest --cov=src
- name: Run linting
run: uv run ruff check .
Troubleshooting
Command not found errors
Problem: Running python or pytest directly doesn't work.
Solution: Always prefix with uv run: uv run python or uv run pytest
Package installation issues
Problem: Package conflicts or resolution errors. Solution: Clear the cache and reinstall:
uv cache clean
uv pip sync requirements.txt
IDE not recognizing packages
Problem: IDE shows import errors despite packages being installed.
Solution: Ensure IDE interpreter points to .venv/bin/python, not system Python.
Different behavior between local and CI
Problem: Tests pass locally but fail in CI.
Solution: Use uv pip sync instead of uv pip install to ensure exact versions.
Best Practices
- Never commit
.venv/- It's already in.gitignore - Always use
uv runfor command execution - Keep requirements.txt updated when adding/removing packages
- Use
uv pip syncfor reproducible environments - Document any special setup in project README
- Avoid activation scripts - Use direct execution instead
Benefits of This Approach
- Explicit Context: Every command clearly shows it's running in the project environment
- No Activation State: Eliminates "which environment am I in?" confusion
- Shell Agnostic: Same commands work in bash, zsh, fish, PowerShell, cmd
- CI/CD Friendly: Commands are identical in local and automated environments
- Faster Execution: uv's Rust implementation provides superior performance
- Simpler Onboarding: New developers don't need to learn activation patterns
Quick Reference Card
# Setup (once)
uv venv
uv pip sync requirements.txt
# Daily commands
uv run python script.py # Run a script
uv run uvicorn src.main:app # Start server
uv run pytest # Run tests
uv run ruff check . # Lint code
uv pip install package # Add package
uv pip list # List packages
uv run python # Interactive shell
Remember: When in doubt, prefix with uv run for Python commands and uv pip for package management.