Contributing¶
Contributions are welcome. This guide covers the development setup, coding standards, and the pull request process.
Development setup¶
CCA-Zoo uses uv for dependency management, both in CI and for
local development. A uv.lock is committed so everyone (and CI) resolves the exact same
dependency versions.
1. Clone and install¶
uv sync creates .venv for you; prefix commands with uv run, or source .venv/bin/activate
first. For documentation development:
For a specific optional extra (e.g. to work on the deep module):
If you don't want to use uv, pip install -e ".[dev]" also works, but won't use the lockfile.
2. Run tests¶
uv run pytest -m "not slow" # fast tests only (no torch / numpyro / xgboost required)
uv run pytest -m slow # deep, probabilistic, and tree tests (requires extras)
uv run pytest --cov=cca_zoo # with coverage report
3. Lint and format¶
uv run ruff check . # lint
uv run ruff format --check . # format check
uv run ruff format . # auto-format
Optionally, install pre-commit to run these (plus mypy) automatically on every commit:
4. Type checking¶
5. Build docs locally¶
uv run mkdocs serve # live-reload preview at http://127.0.0.1:8000
uv run mkdocs build --strict # build static site into site/
Coding standards¶
All contributions must comply with the following:
- Python ≥ 3.11 only. Use
X | Yunions,list[x]/dict[x]/tuple[x]generics. - Google-style docstrings, short and factual. A public class docstring has a one-line
summary, the objective and method in a few sentences (maths where it defines the model),
then
Args(each ending "Default is X."; "Per-view." for parameters that take a scalar or one value per view),Attributes(the fitted attributes specific to the model; the common ones are onBaseModel),Referencesand a runnableExamplessection.fitdocstrings take the form "Fit the model." withArgs,Returns: self.and only model-specificRaises. Private helpers get a line or two. Design rationale, history and comparisons belong in the user guide, not the docstring. - Full type annotations —
mypy --strictmust pass cleanly. - No
try/except— write code that does not need them. - No
print— useloggingif diagnostic output is needed. - 100% test coverage — every new code path needs a test.
- No
# pragma: no cover— this is banned.
Adding a new model¶
- Create the implementation file in the appropriate subpackage
(e.g.
cca_zoo/linear/_mymodel.py). - Inherit from
BaseModel(linear/nonparametric) orBaseDeep(deep). This gets youtransform,fit_transform,predict,inverse_transform,score, and correct sklearnget_params/set_params/tags for free. Implementfit, starting withviews = self._setup_fit(views)and ending withself._fit_maps_and_importances(views)thenreturn self, and setweights_for a linear model; a nonlinear one overrides_transform_view(view, centred), its per-view encoder, which every other method goes through._fit_maps_and_importancesrecords whatpredict,inverse_transformandfeature_importances_per_view_need, so the model does not keep its training data. Override_feature_importances(views)if the model has a native importance (one non-negative array per view); otherwise permutation importance is used. An iterative model reportsn_iter_and warns with sklearn'sConvergenceWarningwhen it stops atmax_iter. - Add Google-style docstrings including the mathematical objective and reference(s).
- Declare every constructor parameter in
_parameter_constraints, merging in the parent class's (e.g.{**BaseModel._parameter_constraints, "shrinkage": RIDGE_PARAMETER};cca_zoo/_utils/_param_constraints.pyhas shared fragments). An invalid value then fails clearly atfit(), as in sklearn. - Export from the subpackage's
__init__.pyand add to__all__. This is what puts the model under the generic tests, so it needs no tests of its own for anything they check: tests/test_estimator_checks.pyruns scikit-learn's estimator checks on it through a two-view adapter: input validation, fitted-state errors, pickling, cloning, idempotent refits, invariance to sample order, and more.tests/test_model_contract.pychecks the multiview contract:transform,predictandinverse_transform, the number and shapes of views, that every parameter is validated,center=False,feature_importances_per_view_, convergence warnings, and that the model recovers a strong shared signal at its defaults.tests/test_invariances.pychecks what the fit must not depend on: stacking the data on itself, the order of the rows and columns, and a whole view's units. If a check cannot apply to the model, add it to that file's expected failures or exemptions with the reason. A model with a hyperparameter that reduces it to another model (no penalty to CCA, no sparsity toPLSCanonical) belongs intests/test_limits.py.- Test only what is specific to the model in
tests/<subpackage>/test_mymodel.py: agreement with a known answer where one exists (a closed form, another model it reduces to, a brute-force optimum), what its parameters do, and the behaviour that motivates it (robustness to outliers, sparsity, an interaction it captures). Do not repeat the generic checks. - Add a
cca_zoo.<subpackage>.MyModelentry to the relevantdocs/api/*.mdpage —tests/test_docs_coverage.pyenforces this. - Open a pull request against
main.
Pull request guidelines¶
- Keep PRs focused — one feature or fix per PR.
- Include tests for all new/changed behaviour.
- Ensure
uv run ruff check .,uv run ruff format --check .,uv run mypy cca_zoo, anduv run pytest -m "not slow"all pass before requesting review. - Reference any related issues in the PR description.
Reporting issues¶
Use GitHub Issues to report bugs or request features. Please include:
- A minimal reproducible example
- The version of cca-zoo (
python -c "import cca_zoo; print(cca_zoo.__version__)") - Your Python version and OS