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.
3.6 KiB
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
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:
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:
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.
core/is pure Python — stdlib + numpy + pydantic. It may not import Qt oropenseespy. Period.services/may usecore+h5py+openseespy, but may not import Qt.views/(PySide6/pyvistaqt) may not importopenseespydirectly — go through a service. No business logic inviews.viewmodels/bridgescore↔ Qt (signals,QUndoStack).commands/holds theQUndoCommandsubclasses; all model mutations go throughcommands, not ad-hoc edits inviews.- Public functions and methods need type hints and a docstring.
- New domain entities go through Pydantic validation.
- Long-running operations (>50 ms) run off the GUI thread (
AnalysisWorkerin aQThread, cancelled viaisInterruptionRequested(); results cross threads as a lightweightResultsHandlewritten to HDF5).
The full package map and the fixed OpenSeesPy command order the runner
emits live in 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 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.