|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +PySide6 desktop application template following MVVM architecture on Linux. Built with Python 3.14, Qt Designer for UI, and pytest for testing. |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +# Setup (first time) |
| 13 | +./setup.sh # Installs UV, creates .venv, installs deps |
| 14 | +source .venv/bin/activate |
| 15 | + |
| 16 | +# Run |
| 17 | +python src/main.py |
| 18 | + |
| 19 | +# Test |
| 20 | +pytest tests/ # All tests |
| 21 | +pytest tests/unit/ # Unit tests only |
| 22 | +pytest tests/integration/ # Integration tests only |
| 23 | +pytest tests/unit/test_example_model.py # Single file |
| 24 | +pytest tests/unit/test_example_model.py::TestExampleModel::test_validate_returns_true_for_valid_data # Single test |
| 25 | +pytest -k "test_pattern" tests/ # By pattern |
| 26 | + |
| 27 | +# Code quality |
| 28 | +black src/ tests/ # Format |
| 29 | +isort src/ tests/ # Sort imports |
| 30 | +mypy src/ # Type check (strict, Python 3.14) |
| 31 | +``` |
| 32 | + |
| 33 | +## Architecture (MVVM — strictly enforced) |
| 34 | + |
| 35 | +Data flows one direction: **Service → Model → ViewModel → View** |
| 36 | + |
| 37 | +Dependencies are injected via constructors in `src/main.py`: |
| 38 | +``` |
| 39 | +Service(created) → ViewModel(receives service) → View(receives viewmodel) |
| 40 | +``` |
| 41 | + |
| 42 | +### Layer rules |
| 43 | + |
| 44 | +| Layer | Location | Qt imports? | Purpose | |
| 45 | +|-------|----------|-------------|---------| |
| 46 | +| **Model** | `src/models/` | **NO** — pure Python | Business logic, validation, dataclasses | |
| 47 | +| **ViewModel** | `src/viewmodels/` | QObject + Signal only | Presentation logic, state via signals | |
| 48 | +| **View** | `src/views/` | Full PySide6 | Load `.ui` files, connect signals, minimal logic | |
| 49 | +| **Service** | `src/services/` | No | External operations, data fetching | |
| 50 | + |
| 51 | +### UI: Qt Designer only — never hardcode layouts in Python |
| 52 | + |
| 53 | +All UI is defined in `.ui` files under `src/views/ui/`, loaded at runtime via `QUiLoader`. Views access widgets with `self.ui.findChild(WidgetType, "objectName")`. Opening the designer: `designer src/views/ui/main_window.ui` |
| 54 | + |
| 55 | +### Signal/slot communication pattern |
| 56 | + |
| 57 | +ViewModels define signals (`data_loaded`, `error_occurred`, `status_changed`). Views connect their widget signals (e.g. `button.clicked`) to ViewModel slots, and observe ViewModel signals to update the UI. No direct method calls across layers. |
| 58 | + |
| 59 | +### Dependency injection via Protocol |
| 60 | + |
| 61 | +Services are typed with `Protocol` from `typing`, not concrete classes. This allows mock injection in tests. |
| 62 | + |
| 63 | +## Branch Protection |
| 64 | + |
| 65 | +- **`testing` branch**: All development happens here |
| 66 | +- **`main` branch**: Protected — only receives merges from `testing` |
| 67 | +- Before modifying files, verify branch: `git branch --show-current` |
| 68 | +- Git hooks enforce this (pre-commit blocks commits to main) |
| 69 | + |
| 70 | +## Testing Conventions |
| 71 | + |
| 72 | +- Framework: pytest + pytest-qt + pytest-mock |
| 73 | +- Pattern: Arrange-Act-Assert |
| 74 | +- Qt tests use `qtbot` fixture and `qtbot.waitSignal()` for signal assertions |
| 75 | +- Session-scoped `qapp` fixture in `tests/conftest.py` provides QApplication |
| 76 | +- Coverage targets: Models 95%+, ViewModels 90%+ |
| 77 | +- Coverage is configured in `pyproject.toml` (runs automatically with `pytest`) |
| 78 | + |
| 79 | +## Configuration |
| 80 | + |
| 81 | +All tool config lives in `pyproject.toml`: |
| 82 | +- **pytest**: `--cov=src`, verbose, strict markers |
| 83 | +- **mypy**: strict mode, Python 3.14, PySide6 imports ignored |
| 84 | +- **black**: line-length 88, target py314 |
| 85 | +- **isort**: black-compatible profile |
0 commit comments