curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv
source .venv/bin/activate
uv pip install -r requirements.txtAll development happens on the testing branch. main is protected and only receives human-authorized merges from testing.
git checkout testing- Write tests first (TDD)
- Implement in the correct MVVM layer
- Run full test suite before committing
pytest tests/ # runs tests + coverage automatically
mypy src/ # type check
black src/ tests/ # format
isort src/ tests/ # import order| Layer | Allowed | Forbidden |
|---|---|---|
models/ |
Pure Python, dataclasses, validation | Any Qt import |
viewmodels/ |
QObject, Signal/Slot, call services | Direct widget access |
views/ |
Load .ui files, findChild(), signal connections | Business logic |
services/ |
File I/O, external APIs | Qt imports |
New dependencies between layers must flow downward only. Never skip layers.
Each ViewModel defines its own ServiceProtocol (using typing.Protocol) in the same file as the ViewModel itself.
Design in Qt Designer, save to src/views/ui/. Never hardcode layouts in Python. Widget objectName values in .ui files must match what findChild() calls in the corresponding view. See DESIGN.md Appendix A for the canonical objectName list.
- Type hints required on all functions (
mypystrict mode enforced) - Google-style docstrings on all public APIs
- Signals for all cross-layer communication — no direct method calls from ViewModel into View
- Long operations must run in
QThread— never block the UI thread
feat: add encoding conversion model
fix: signal not emitted on empty result
test: add edge cases for find/replace viewmodel
docs: update widget objectNames in DESIGN.md
- Branch is
testing, notmain -
pytest tests/passes -
mypy src/passes with 0 errors - MVVM layer boundaries respected
- No Qt imports in models or services