-
Notifications
You must be signed in to change notification settings - Fork 1
Contributing
NNx is a small library; the goal is to keep it small, tested, and useful for the existing notebook consumers while inviting new ones. Bug reports and PRs are welcome via GitHub issues.
For the full reference, see the canonical file: CONTRIBUTING.md.
git clone https://github.com/thekaveh/NNx.git
cd NNx
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install # optional but recommendedVerify a clean baseline:
pytest # full suite (~15s on CPU)
ruff check src/ tests/ examples/ # lint
ruff format --check src/ tests/ examples/ # format check (matches CI + pre-commit)
mkdocs build --strict # docs (gates CI)Useful env var: NNX_TQDM_DISABLE=1 silences the training progress bar — set this in CI or non-TTY contexts. The test suite's conftest.py already does this session-wide.
- Open an issue first for non-trivial changes — saves churn if the design is off. Tiny fixes can go straight to PR.
-
Branch from
main. Name branches descriptively (fix/...,feat/...,docs/...,refactor/...). -
Write tests. Every PR that changes behavior should land with a focused test that fails on
mainand passes on the branch. The existingtests/test_*_series.pyfiles (organized by audit pass) are good models. - Keep PRs small. One coherent change per PR is much easier to review than a sweeping mix.
These are non-negotiable:
-
Strict back-compat for the existing notebook consumer. Don't rename, remove, or restructure public APIs without a migration path. Don't change the on-disk
runs/<id>/format. -
Omit-when-default rule. New fields on params dataclasses must omit themselves from
.state()when set to their defaults. This preservesrun.idhashes for all existing runs — a non-default field shifts the hash and breaks warm-resume. See the regression tests intests/test_params_round_trip.py(search fortest_nn_*_state_omits_*_when_*) for the canonical pattern. The test must use an explicitassert "<field>" not in state()form — a round-trip test alone is insufficient. -
State / from_state round-trip. Every params dataclass with a
state()method must round-trip cleanly throughfrom_state(state()). Enforced bytests/test_params_round_trip.py. -
Breaking on-disk format changes require a versioned reader. Public API renames require a deprecation shim and a
__getattr__alias for at least one minor version.
pytest # full suite
pytest tests/test_pass2_n_series.py::test_n7_evaluate_aggregates_across_batches
pytest -k "graph" # name filter
pytest --cov=nnx --cov-report=term-missing # with coverageTests live under tests/. Rules:
- Tests run on CPU and must finish fast (keep new tests under a few seconds).
- Use small
TensorDatasetfixtures fromtests/conftest.py. - Code without tests will not be merged.
- Dependencies added to the core
[project.dependencies]list will not be merged if they can go under[project.optional-dependencies]instead.
-
ruff enforces formatting and lint (
E F W B I UP). Runruff check --fix src/ tests/ examples/andruff format src/ tests/ examples/before pushing. Pre-commit handles both automatically when installed. -
Type annotations are encouraged on new code. pyright (basic mode) runs in CI, with
--strictplanned over time. - Docstrings on public functions / classes explain the why (constraints, edge cases) — not just the what.
- Comments explain non-obvious decisions, hidden constraints, or surprising behavior.
- Push to your fork and open a PR against
main. - Fill in the PR template (Summary / Test plan).
- Wait for CI to go green (lint + format + tests + mkdocs on Python 3.10 / 3.11 / 3.12).
- Address review comments by pushing new commits — we squash on merge.
- Add a one-line entry under
[Unreleased]inCHANGELOG.mdfor any user-visible change.
NNx uses release-please for automated version bumps, changelog updates, and tagging. Contributors don't touch versions or tags — just write a Conventional Commit-style PR title (feat:, fix:, chore:, docs:, etc.).
The end-to-end release flow:
- Every merge to
mainupdates a long-lived "Release" PR maintained byrelease-please.yml. The PR accumulates the next version +CHANGELOG.mddiff. Pre-1.0:feat:triggers a minor bump (0.X.0);fix:and most other types trigger a patch bump (0.X.Y). - A maintainer merges the Release PR when ready to ship. That merge pushes a
v*tag. - The tag push fires
release.yml: full test matrix → build → OIDC-trusted publish to PyPI →verify-publishedconfirmspip install thekaveh-nnx==X.Y.Zworks from a clean venv.
By contributing you agree that your contribution will be licensed under the Apache License 2.0.
- Params-and-Back-Compat — deep dive on the omit-when-default rule and state() contract
- Releases-and-Changelog — release-please flow and changelog structure
- CONTRIBUTING.md (canonical)
Apache-2.0 licensed.