Contributing
Thanks for considering a contribution. pybmodes is a
research-grade engineering library — most contributions will
involve numerical validation, structural-dynamics
references, or input-format support. The guidance below
is what we’ve learned keeps the project shippable.
Who this is for
End users filing an issue or feature request — see Installation for setup, then the issue templates on GitHub.
Contributors opening a pull request — read on through
CONTRIBUTING.mdbelow.Maintainers preparing a release — see Release checklist.
Scope of welcome contributions
In rough order of “easiest to land”:
Documentation fixes — typos, clarifications, missing examples in the docs you’re reading.
Validation matrix additions — new cross-check against a citable reference (paper, BModes JJ run, BeamDyn run). Add the test + the matrix row in the same PR; the mechanical audit blocks claims without tests.
Input-format support — new dialect of an existing reader, a new keyword on an existing constructor, a new
Tower.from_Xfor an industry-standard input that pyBmodes doesn’t yet read.Bug fixes — anything where a published reference and pyBmodes disagree by more than the documented tolerance. Use the validation discrepancy issue template to anchor the report.
Performance improvements — speedups that come with a benchmark script; the existing
scripts/benchmark_sparse_solver.pyis the model.
Out of scope (will be politely closed):
Wholesale rewrites of the FEM core that change validation numbers without a corresponding tightening of the tolerance and an updated matrix.
New runtime dependencies for the core (the
numpy + scipy-only stance is a contract; new deps go in an extra).Refactor-only PRs touching the public API without a user-visible benefit.
The contribution guide
Contributing to pyBmodes
Thanks for considering a contribution. pyBmodes is a research-grade engineering library — most contributions will involve numerical validation, structural-dynamics references, or input-format support. The guidance below is what we’ve learned keeps the project shippable.
Quick start
git clone https://github.com/SMI-Lab-Inha/pyBModes.git
cd pyBModes
python -m venv .venv && source .venv/bin/activate # or conda env
pip install -e ".[dev,plots]"
pytest
The default pytest run uses only self-contained tests (synthetic decks + closed-form references). The integration marker gates tests that need upstream OpenFAST / BModes data; place those clones under external/ (gitignored). See installation for the full Windows + conda quickstart.
Ground rules
1. Stage explicit paths
Never git add -A or git add .. Untracked upstream-data directories under external/ would leak in as embedded-repo gitlinks. Stage by name:
git add src/pybmodes/campbell.py tests/test_campbell.py
3. No tool / vendor attribution in tracked content
Code comments, CHANGELOG entries, test docstrings, and documentation must not name AI assistants, external review consultancies, or individual reviewers. Use neutral engineering provenance: “static review”, “follow-up”, “regression”. Issue numbers (issue #54) are fine and encouraged.
4. Independence stance
The default test suite must run on a fresh clone with no external data. Don’t introduce a default-run test that requires data outside external/. Mark data-dependent tests with @pytest.mark.integration (or pytestmark = pytest.mark.integration for whole modules).
5. Validate against citable references
When adding a new test that exercises FEM behaviour, cite the reference (textbook, peer-reviewed paper, NREL technical report). The validation matrix in VALIDATION.md is the single source of truth and is mechanically audited by scripts/audit_validation_claims.py in CI.
Development workflow
Pre-commit
Install hooks once per clone:
pip install pre-commit
pre-commit install
This runs ruff (auto-fix), the standard hygiene hooks (trailing-whitespace, end-of-file-fixer, YAML / TOML validation, large-file guard, merge-conflict marker check), codespell, and insert-license — which inserts the Apache 2.0 boilerplate header into any new .py file under src/pybmodes/, scripts/, cases/, or noxfile.py that doesn’t already have it (template at .license_header.txt). To run manually:
pre-commit run --all-files
Lint + type-check + audit
ruff check src/ tests/ scripts/
mypy src/pybmodes
python scripts/audit_validation_claims.py
CI matches this exact scope. The audit_validation_claims.py script gates “claim ahead of test” drift — every test-file link in VALIDATION.md must point at a file containing at least one def test_… method.
Running tests
pytest # self-contained (default)
pytest -m integration # needs external/ data
pytest tests/test_campbell.py # one module
pytest -k "blade_label" # by keyword
Building the docs locally
pip install -e ".[docs]"
make -C docs strict # treats warnings as errors (mirrors Read the Docs + CI)
open docs/_build/html/index.html
Using nox
A noxfile.py ships pre-built sessions for the common loops:
nox -s lint # ruff
nox -s type # mypy
nox -s tests # pytest -m 'not integration'
nox -s docs # sphinx-build -W
nox -s build # python -m build (sdist + wheel)
Pull-request checklist
Before opening a PR:
Tests pass:
pytest(default) andpytest -m integrationif you touched data-dependent code.Lint clean:
ruff check src/ tests/ scripts/.Type-check clean:
mypy src/pybmodes.Validation audit clean:
python scripts/audit_validation_claims.py.If you added a public name, it’s listed in
src/pybmodes/__init__.py’s docstring and (if applicable) the README’s Public API section.If you changed numerical behaviour,
CHANGELOG.mdcalls out the magnitude under Fixed / Changed and a regression test pins the new behaviour.Commit message follows the project’s conventional-ish style (look at
git log --oneline -20for examples).
Release process
For maintainers, the full pre-tag sequence is in https://pybmodes.readthedocs.io/en/latest/release_checklist.html.
Reporting issues
Open a GitHub issue. For security-sensitive reports, see SECURITY.md.
Code of conduct
This project follows the Contributor Covenant.