Snapshots the current development tree, headlined by proper load combinations (user request): a reusable LoadCombination entity of weighted completed static-case results (e.g. 1.2xDead + 1.6xLive). - core: LoadCombination/LoadCombinationItem entities, Project integration (lookup, unique ids, reference validation) - services: combinations.py (linear superposition + envelope), exported via services __init__ - commands: undoable Add/Delete/Update for combinations - GUI: Load Combinations manager dialog, Run-dialog evaluation, envelope display in Results panel, Combinations tab in Table dock - tests: unit coverage (validation, math, error paths) + integration superposition check vs a single factored run
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.