Catch-all for the intermixed residue of the unpushed otko-development work ported into this tree: combinations/console-dock/quick-guide wiring across commands, core, services, views and tests; repo-wide ruff-format normalization; README/CONTRIBUTING updates; and the toolbar default (both toolbars now open in the top area, quick guide text updated). Splitting this further would require hunk-level surgery with low confidence; the preceding commits in this branch isolate the self-contained features.
97 lines
3.6 KiB
Markdown
97 lines
3.6 KiB
Markdown
# Contributing
|
||
|
||
Thanks for helping with OTKO — a SAP2000-style desktop GUI for
|
||
OpenSeesPy. Early-stage project: the bar is architecture cleanliness, not
|
||
feature count. If your change breaks a layering rule below, it won't
|
||
merge — no matter how useful the feature.
|
||
|
||
## Dev setup
|
||
|
||
```bash
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Linux / macOS
|
||
# .venv\Scripts\activate # Windows
|
||
pip install -e ".[gui,dev]"
|
||
pre-commit install
|
||
```
|
||
|
||
`pip install -e ".[gui,dev]"` pulls the Qt/PyVista desktop stack plus the
|
||
dev tools. For a headless checkout (core + services only, no Qt) use
|
||
`pip install -e .` instead. Python 3.10+; on Windows use 3.12+.
|
||
|
||
Launch the GUI with:
|
||
|
||
```bash
|
||
python -m otko
|
||
```
|
||
|
||
`pre-commit install` wires ruff + mypy into your local git hooks so
|
||
obvious issues are caught before a commit. Run it once per clone.
|
||
|
||
## Before opening a PR
|
||
|
||
Run the verify commands in this order and make sure they are all clean:
|
||
|
||
```bash
|
||
ruff check src tests
|
||
ruff format src tests # line-length 100, E501 ignored
|
||
mypy src/otko/core src/otko/services
|
||
pytest -m "not slow" # CI gate: lint → this, on 3.10/3.11/3.12 × ubuntu/windows/macos
|
||
```
|
||
|
||
Focused runs are faster while iterating: `pytest tests/unit` (pure logic,
|
||
milliseconds), `pytest tests/gui -k <name>` (pytest-qt, needs a display;
|
||
Linux GUI tests want `xvfb-run -a pytest ...`), and
|
||
`pytest tests/integration -k <name>` (real OpenSeesPy runs). Single test:
|
||
`pytest tests/unit/test_project.py::test_name -q`. Markers: `gui`, `slow`.
|
||
|
||
## Architectural rules (enforced in review)
|
||
|
||
OTKO uses a strict one-way **MVVM + service** architecture. Dependencies
|
||
flow outward-in only:
|
||
|
||
```
|
||
views → viewmodels → services → core
|
||
```
|
||
|
||
`commands` sits alongside the bridge and owns every model mutation.
|
||
|
||
1. `core/` is pure Python — stdlib + numpy + pydantic. It may **not**
|
||
import Qt or `openseespy`. Period.
|
||
2. `services/` may use `core` + `h5py` + `openseespy`, but may **not**
|
||
import Qt.
|
||
3. `views/` (PySide6/pyvistaqt) may **not** import `openseespy` directly —
|
||
go through a service. No business logic in `views`.
|
||
4. `viewmodels/` bridges `core` ↔ Qt (signals, `QUndoStack`).
|
||
5. `commands/` holds the `QUndoCommand` subclasses; all model mutations
|
||
go through `commands`, not ad-hoc edits in `views`.
|
||
6. Public functions and methods need type hints and a docstring.
|
||
7. New domain entities go through Pydantic validation.
|
||
8. Long-running operations (>50 ms) run off the GUI thread (`AnalysisWorker`
|
||
in a `QThread`, cancelled via `isInterruptionRequested()`; results cross
|
||
threads as a lightweight `ResultsHandle` written to HDF5).
|
||
|
||
The full package map and the fixed OpenSeesPy command order the runner
|
||
emits live in [`docs/architecture.md`](docs/architecture.md). Never
|
||
reorder the runner's commands.
|
||
|
||
## Branch model
|
||
|
||
`main` is the default and integration branch. Work on short-lived topic
|
||
branches cut from `main` — `feat/<topic>`, `fix/<topic>`, or
|
||
`docs/<topic>` — and open a pull request against `main`. Do not commit
|
||
directly to `main` from an agent session. There is no `develop` branch.
|
||
|
||
## Commit style
|
||
|
||
Conventional Commits — `feat:`, `fix:`, `refactor:`, `docs:`, `test:`,
|
||
`chore:`, `ci:`. Keep each commit focused; a `feat:` commit should add a
|
||
feature, not mix one in with unrelated refactors.
|
||
|
||
## Documentation
|
||
|
||
If your change is user-visible, update
|
||
[`docs/QUICK_GUIDE.md`](docs/QUICK_GUIDE.md) and the relevant roadmap or
|
||
ADR entry. Project model files are `.osmodel` (Pydantic-validated JSON);
|
||
regenerate the checked-in `examples/*.osmodel` from their scripts with
|
||
`python examples/<name>.py` rather than hand-editing them.
|