Contributing to industrialstats¶
Thank you for considering a contribution. This project is pre-1.0 and its first priority is statistical correctness, so the guidelines below place more weight on validation than a typical library would.
By participating you agree to abide by our Code of Conduct.
Getting set up¶
With Poetry, which reads the dev group from pyproject.toml directly:
git clone https://github.com/DiogoRibeiro7/industrialstats.git
cd industrialstats
poetry install --with dev
poetry run pre-commit install
With pip. The dev dependencies are declared as a Poetry group rather than a PEP 621 extra, so pip cannot resolve them from the project and they are listed explicitly:
git clone https://github.com/DiogoRibeiro7/industrialstats.git
cd industrialstats
python -m pip install -e . \
pytest pytest-cov hypothesis ruff mypy pre-commit \
pandas-stubs types-openpyxl types-PyYAML
pre-commit install
The stub packages matter: mypy reports different results without them, so
install the full set or your local run will not match CI.
Run the checks:
pytest # tests; src/ is on the path automatically
pytest -m "not benchmark" # skip the timing-based performance checks
ruff check . # lint
ruff format . # format
mypy # type check
pre-commit run --all-files # everything the CI quality job runs
Statistical validation¶
This is the part that matters most.
Shape and run-count assertions are not sufficient for statistical code. A test asserting that a 2^3 factorial has 8 rows tells you almost nothing about whether the design is correct.
When you add or change a statistical method, the pull request must include at least one of:
- A comparison against an independent reference — a worked example from a textbook, or output from reference software such as R, SAS, JMP, Minitab, or Design-Expert. Cite it precisely (author, edition, page or example number; or the exact code and package version).
- An algebraic property test — orthogonality of the design matrix, the defining relation of a fraction, the resolution implied by its generators, variance-balance of a block design, and so on.
- A Monte Carlo recovery test — simulate from known effects with a fixed seed and confirm the method recovers them within a stated tolerance.
Existing examples worth reading before you write yours live in
tests/test_validation/test_statistical_accuracy.py and the property tests in
tests/test_designs/.
Randomization must be seedable, and tests must be deterministic. Hypothesis
profiles are registered in tests/conftest.py; the ci profile is used in
continuous integration.
Labelling maturity honestly¶
If a method is provisional, say so — in its docstring, in the README table, and in the roadmap. A design family that is present but statistically unverified is worse than an absent one if users cannot tell the difference.
Code style¶
Formatting and linting are handled by Ruff,
which replaces black, isort, and flake8. pre-commit applies it automatically;
CI enforces it.
- Public functions need NumPy-style docstrings covering parameters, returns, and raised exceptions. These docstrings are published as the API reference, so they are user-facing.
- Type hints are required on new code.
- Mathematical notation is welcome where it is the clearest spelling. Names
like
X,XtX, andSS_Aare exempt from the usual casing rules insidesrc/industrialstats/. - Use DataExcept types at data
and operational boundaries — file loading, schema problems, export failures —
and preserve the original exception as the cause. Do not mechanically
convert mathematical precondition failures; a singular design matrix should
stay a
ValueError.
Type checking¶
mypy runs over src/industrialstats and must pass.
A small number of numerically dense modules still carry pre-existing type
errors and are listed under [[tool.mypy.overrides]] in pyproject.toml with
ignore_errors = true. That list is a ratchet:
- it may shrink at any time — removing a module from it is a welcome PR on its own;
- it must not grow. New code is expected to type-check. If you genuinely cannot
satisfy the checker because of third-party stub limitations, use a narrow
# type: ignore[error-code]with a comment explaining why, rather than disabling checking for a whole module.
Test coverage¶
CI enforces a coverage floor. Like the typing ratchet, the floor only moves up. If your change lowers coverage below it, add tests rather than lowering the threshold.
Commits and pull requests¶
- Branch from
mainand open a pull request againstmain. - The repository uses Conventional Commits
(
feat:,fix:,docs:,chore:,test:,refactor:). - Add an entry under
## [Unreleased]inCHANGELOG.mdfor anything user-visible. - Fill in the pull request template, including the statistical validation section when it applies.
Documentation¶
The site is built with MkDocs Material and mkdocstrings:
python -m pip install mkdocs mkdocs-material "mkdocstrings[python]"
mkdocs serve # preview at http://127.0.0.1:8000
mkdocs build --strict
--strict is what CI runs, so broken cross-references fail the build. The API
reference is generated from docstrings, so improving a docstring improves the
site.
Reporting issues¶
Use the issue templates. For a wrong statistical result, use the Statistical correctness template — it asks for the reference value needed to verify a fix, which is what makes the report actionable.
Security problems should be reported privately; see SECURITY.md.