# Developer Tools Guide
This document explains the developer tools used in this project, what they do, and why we chose them.
## Overview
We use a modern Python development stack focused on:
- **Speed**: Fast tools that don't slow down development
- **Quality**: Catch bugs and issues early
- **Consistency**: Maintain uniform code style across the project
- **Type Safety**: Leverage Python's type hints for better code reliability
## Package Manager: uv
**What it is**: A fast, modern Python package and project manager written in Rust.
**Why we use it**:
- **Speed**: 10-100x faster than pip for package installation
- **Reliability**: Better dependency resolution than pip
- **Modern**: Built-in support for virtual environments and project management
- **Compatible**: Works with existing `pyproject.toml` and `requirements.txt`
- **Virtual Environment**: Automatically creates and manages `.venv` directory
**Common commands**:
```bash
# Install dependencies
uv sync
# Install with dev dependencies
uv sync --all-extras
# Add a new package
uv add httpx
# Add a dev dependency
uv add --dev pytest
# Run commands in the virtual environment
uv run python script.py
uv run pytest
```
**Resources**:
- Website: https://astral.sh/uv
- Docs: https://docs.astral.sh/uv/
---
## Code Formatter: Black
**What it is**: An opinionated Python code formatter.
**Why we use it**:
- **Zero Configuration**: No debates about style, it just formats
- **Consistent**: Produces the same output every time
- **Fast**: Reformats large codebases in seconds
- **Community Standard**: Widely adopted in the Python ecosystem
**Configuration**: Set in `pyproject.toml`:
```toml
[tool.black]
line-length = 100
target-version = ["py311"]
```
**Usage**:
```bash
# Format all code
uv run black src/ tests/
# Check without modifying
uv run black --check src/ tests/
# Show what would change
uv run black --diff src/ tests/
```
**What it does**:
- Enforces consistent indentation and spacing
- Normalizes string quotes
- Formats imports and function signatures
- Wraps long lines intelligently
**Resources**:
- Website: https://black.readthedocs.io/
- Why Black?: https://black.readthedocs.io/en/stable/the_black_code_style/index.html
---
## Linter: Ruff
**What it is**: An extremely fast Python linter and code quality checker, written in Rust.
**Why we use it**:
- **Speed**: 10-100x faster than Flake8, pylint, etc.
- **Comprehensive**: Replaces multiple tools (Flake8, isort, pydocstyle, etc.)
- **Auto-fix**: Can automatically fix many issues
- **Modern**: Actively developed with frequent updates
- **Extensive Rules**: Covers 700+ rules from various linting tools
**Configuration**: Set in `pyproject.toml`:
```toml
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort (import sorting)
"N", # pep8-naming
"UP", # pyupgrade (modern Python idioms)
"B", # flake8-bugbear (bug detection)
"SIM", # flake8-simplify (simplification suggestions)
# ... and many more
]
```
**Usage**:
```bash
# Check all files
uv run ruff check src/ tests/
# Check and auto-fix
uv run ruff check --fix src/ tests/
# Watch mode (re-check on file changes)
uv run ruff check --watch src/ tests/
```
**What it catches**:
- Syntax errors and undefined names
- Unused imports and variables
- Incorrect import order
- Potential bugs (e.g., mutable default arguments)
- Code complexity issues
- Security vulnerabilities
- Non-Pythonic code patterns
- And much more!
**Resources**:
- Website: https://docs.astral.sh/ruff/
- Rules: https://docs.astral.sh/ruff/rules/
---
## Type Checker: MyPy
**What it is**: A static type checker for Python.
**Why we use it**:
- **Catch Bugs Early**: Find type-related bugs before runtime
- **Better IDE Support**: Enables better autocomplete and refactoring
- **Documentation**: Type hints serve as inline documentation
- **Gradual Typing**: Works with partially-typed codebases
**Configuration**: Set in `pyproject.toml`:
```toml
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
# ... strict typing enabled
```
**Usage**:
```bash
# Check all files
uv run mypy src/
# Check specific file
uv run mypy src/ns_bridge/server.py
# Show error codes
uv run mypy --show-error-codes src/
```
**What it does**:
```python
# MyPy catches issues like:
def get_price(price: int) -> str:
return price # Error: incompatible return type
def search(query: str | None) -> list[str]:
results = query.split() # Error: query might be None
return results
```
**Resources**:
- Website: https://mypy-lang.org/
- Docs: https://mypy.readthedocs.io/
- Cheat Sheet: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
---
## Testing: pytest
**What it is**: A mature, full-featured Python testing framework.
**Why we use it**:
- **Simple**: Easy to write and understand tests
- **Powerful**: Advanced features like fixtures and parametrization
- **Extensible**: Rich plugin ecosystem
- **Async Support**: Works well with async/await code
**Plugins we use**:
- **pytest-asyncio**: Test async functions
- **pytest-cov**: Code coverage reporting
- **pytest-httpx**: Mock HTTP requests for API testing
**Configuration**: Set in `pyproject.toml`:
```toml
[tool.pytest.ini_options]
minversion = "8.0"
testpaths = ["tests"]
pythonpath = ["src"]
asyncio_mode = "auto"
```
**Usage**:
```bash
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov
# Run specific test file
uv run pytest tests/test_models.py
# Run tests matching a pattern
uv run pytest -k "test_station"
# Verbose output
uv run pytest -v
# Stop on first failure
uv run pytest -x
```
**Example test**:
```python
import pytest
from ns_bridge.models import Station
def test_station_creation():
station = Station(name="Utrecht Centraal", code="ut")
assert station.name == "Utrecht Centraal"
assert station.code == "ut"
@pytest.mark.asyncio
async def test_api_client():
# Test async code
result = await some_async_function()
assert result is not None
```
**Resources**:
- Website: https://pytest.org/
- Docs: https://docs.pytest.org/
---
## Coverage: pytest-cov
**What it is**: Code coverage measurement for pytest.
**Why we use it**:
- **Visibility**: See which code is tested
- **Quality**: Identify untested code paths
- **Reports**: Generate HTML coverage reports
**Configuration**: Set in `pyproject.toml`:
```toml
[tool.coverage.run]
source = ["src"]
branch = true
[tool.coverage.report]
precision = 2
show_missing = true
```
**Usage**:
```bash
# Run tests with coverage
uv run pytest --cov
# Generate HTML report
uv run pytest --cov --cov-report=html
# View report (opens in browser)
open htmlcov/index.html
```
**What it shows**:
```
---------- coverage: platform darwin, python 3.11.0 -----------
Name Stmts Miss Cover
-----------------------------------------------------
src/ns_bridge/__init__.py 2 0 100%
src/ns_bridge/config.py 15 2 87%
src/ns_bridge/models.py 45 0 100%
src/ns_bridge/ns_api_client.py 89 12 87%
src/ns_bridge/server.py 124 28 77%
-----------------------------------------------------
TOTAL 275 42 85%
```
---
## Recommended Workflow
### Before Committing
Run this checklist before committing code:
```bash
# 1. Format code
uv run black src/ tests/
# 2. Lint and auto-fix
uv run ruff check --fix src/ tests/
# 3. Type check
uv run mypy src/
# 4. Run tests
uv run pytest --cov
```
### IDE Integration
Most IDEs support these tools:
**VS Code**:
- Install Python extension
- Install Black Formatter extension
- Install Ruff extension
- Install MyPy extension
**PyCharm**:
- Built-in support for Black, MyPy, pytest
- Configure in Settings → Tools → Python Integrated Tools
### Pre-commit Hooks (Optional)
You can automate these checks with pre-commit hooks:
```bash
# Install pre-commit
uv add --dev pre-commit
# Set up hooks
uv run pre-commit install
# Now checks run automatically on git commit
```
---
## Why This Stack?
### Performance
All our tools are either written in Rust (uv, Ruff) or highly optimized (Black, MyPy, pytest). This means:
- Linting takes seconds, not minutes
- Formatting is nearly instant
- Type checking is fast enough to run on every save
### Modern Python
These tools encourage modern Python practices:
- Type hints everywhere
- Async/await patterns
- Latest Python features (3.11+)
- Pydantic for data validation
### Industry Standard
These tools are used by major Python projects:
- FastAPI uses Ruff and MyPy
- Django uses Black
- Many companies use this exact stack
### Developer Experience
- **Fast feedback**: See issues immediately
- **Auto-fix**: Many issues fixed automatically
- **Clear errors**: Helpful error messages with suggestions
- **IDE integration**: Works seamlessly with editors
---
## Troubleshooting
### "Module not found" errors
Make sure you're running commands with `uv run`:
```bash
# Wrong
pytest
# Correct
uv run pytest
```
### Type checking errors
If MyPy complains about missing type stubs:
```bash
uv add --dev types-httpx
```
### Import errors in tests
Ensure `pythonpath = ["src"]` is set in `pyproject.toml` under `[tool.pytest.ini_options]`.
---
## Learn More
- **uv**: https://docs.astral.sh/uv/
- **Black**: https://black.readthedocs.io/
- **Ruff**: https://docs.astral.sh/ruff/
- **MyPy**: https://mypy.readthedocs.io/
- **pytest**: https://docs.pytest.org/
## Questions?
These tools have excellent documentation. If you're unsure about an error or warning, the error messages usually include links to detailed explanations.