## Project Overview Brief description of what this project does and its main purpose. ## Tech Stack - Python 3.x - Key dependencies: (list main libraries) ## Project Structure ``` project/ ├── src/ # Source code ├── tests/ # Test files ├── docs/ # Documentation └── requirements.txt ``` ## Development Guidelines ### Code Style - Follow PEP 8 - Use `ruff` for linting, formatting, and import sorting - Use type hints where appropriate - Document functions with docstrings ### Testing - Run tests: `pytest` - Maintain test coverage above 80% - Run all tests using the `uv` environment ### Common Commands ```bash # Install dependencies pip install -r requirements.txt # Run tests pytest # Lint ruff check src/ # Format ruff format src/ # Lint and auto-fix ruff check --fix src/ ``` ## Key Context for AI Assistance ### Python Version & Compatibility - Python version: 3.x (specify minimum version, e.g., 3.9+) - Main entry point: (e.g., `src/main.py`) ### Code Quality Standards **Type Hints** - Use type hints for all function signatures - Use `typing` module for complex types (List, Dict, Optional, Union) - Return types are mandatory, even for `None` - Example: ```python def process_data(items: list[dict[str, Any]], threshold: float = 0.5) -> dict[str, int]: ... ``` **DRY (Don't Repeat Yourself)** - Extract shared logic into functions or classes when you see the same pattern repeated 3+ times - Prefer a single source of truth for constants, configuration values, and business rules - Use inheritance, mixins, or composition to share behavior across classes rather than copying methods - Keep utility/helper functions in dedicated modules so they're discoverable and reusable - When fixing a bug, check if the same pattern exists elsewhere and fix all instances **Ruff** - Use `ruff` as the single tool for linting, formatting, and import sorting - Configure ruff in `pyproject.toml` under `[tool.ruff]` - Run `ruff check --fix` to auto-fix lint violations where possible - Run `ruff format` to format code (replaces black) - Ruff handles import sorting automatically (replaces isort) — configure via `[tool.ruff.lint.isort]` if needed **Error Handling** - Use specific exception types, never bare `except:` - Always include context in error messages - Use custom exceptions for domain-specific errors - Validate inputs early and explicitly **Docstrings** - Use Google or NumPy style docstrings consistently - Document parameters, return values, and raised exceptions - Include usage examples for complex functions **Logging** - Use Python's `logging` module, not `print()` - Set appropriate log levels (DEBUG, INFO, WARNING, ERROR) - Include contextual information in log messages **Class Design — Avoid Custom `__init__` Methods** - Prefer `@dataclass` (or `attrs`) over hand-written `__init__` methods. The generated `__init__` simply assigns attributes with no hidden side effects. - For complex or async construction, use `@classmethod` factory methods instead of stuffing logic into `__init__`. Classmethods can be async, return different types, or offer multiple named construction paths. - Use `typing.NewType` to enforce domain constraints on primitive types (e.g., `UserId = NewType("UserId", int)`) so objects are valid by construction. - Never perform I/O (file reads, network calls, database queries) inside `__init__`. Move that work into a classmethod factory. - This keeps classes easy to test (construct with plain attribute values, no mocking needed) and easy to extend. **Resource Management** - Always use context managers (`with` statements) for files, connections, locks - Close resources explicitly if context managers aren't available - Handle cleanup in `finally` blocks when needed **Security Practices** - Never hardcode secrets, API keys, or credentials - Use environment variables or secret management services - Validate and sanitize all external inputs - Use parameterized queries for database operations **Performance Considerations** - Prefer list comprehensions over loops for simple transformations - Use generators for large datasets - Profile before optimizing - Document any performance-critical sections **Testing Requirements** - Write tests before or alongside code (TDD encouraged) - Use pytest fixtures for setup/teardown - Mock external dependencies - Test edge cases and error conditions - Aim for >80% coverage **Testing Standards** Testing Checklist: 1. SHOULD parameterize inputs (no magic numbers/strings) 2. SHOULD NOT add test unless it can fail for real defect 3. SHOULD ensure description matches expect assertion 4. SHOULD compare to independent expectations, not function output 5. SHOULD follow same lint/type-safety as prod code 6. SHOULD express invariants/axioms (use `hypothesis` for property tests) 7. Unit tests grouped under `describe_function_name` 8. Use `pytest.approx(...)` for variable parameters 9. ALWAYS use string assertions (`==`) vs `toBeGreaterThan(0)` / `assertEqual` 10. SHOULD test edge cases, realistic input, boundaries 11. SHOULD NOT test conditions caught by type checker Test Types: - **Unit tests**: Colocated `*_test.py` in same directory - **Integration tests**: Separate from unit tests (don't mock DB) - **Property-based tests**: Use `hypothesis` for invariants **Dependencies** - When Claude runs or tests code, use `uv run` to automatically execute in the virtual environment: - Use `uv add` to add dependencies (updates pyproject.toml and uv.lock) - uv.lock ensures reproducible installs across environments - Keep dependencies minimal - Document why non-obvious dependencies are needed - Virtual environments are automatically managed by uv ### Architectural Patterns - (Add project-specific patterns, e.g., "Use dependency injection", "Follow repository pattern") - (Note any design patterns in use: Factory, Strategy, etc.) ### Project-Specific Conventions - (Add naming conventions, module organization rules) - (Note any framework-specific patterns if using Django, FastAPI, etc.) - (Document any custom decorators or utilities)