lme-python 0.1.9__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lme_python-0.2.1/.github/dependabot.yml +10 -0
- lme_python-0.2.1/.github/workflows/audit.yml +62 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/.github/workflows/benchmarks.yml +21 -12
- lme_python-0.2.1/.github/workflows/cache-prime.yml +115 -0
- lme_python-0.2.1/.github/workflows/ci.yml +254 -0
- lme_python-0.2.1/.github/workflows/crate-publish-dry-run.yml +48 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/.github/workflows/fuzz-smoke.yml +17 -6
- lme_python-0.2.1/.github/workflows/python-release.yml +182 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/.github/workflows/repo-metadata.yml +4 -1
- lme_python-0.2.1/AGENTS.md +100 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/BENCHMARKS.md +124 -23
- {lme_python-0.1.9 → lme_python-0.2.1}/BENCHMARK_COVERAGE.md +18 -15
- {lme_python-0.1.9 → lme_python-0.2.1}/CHANGELOG.md +72 -2
- lme_python-0.2.1/CI_PERFORMANCE.md +63 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/CONTRIBUTING.md +38 -12
- {lme_python-0.1.9 → lme_python-0.2.1}/Cargo.lock +11 -173
- {lme_python-0.1.9 → lme_python-0.2.1}/Cargo.toml +21 -4
- {lme_python-0.1.9 → lme_python-0.2.1}/GUIDE.md +246 -16
- lme_python-0.2.1/LICENSES/Apache-2.0.txt +193 -0
- lme_python-0.2.1/LICENSES/BSD-3-Clause-OpenBLAS.txt +31 -0
- lme_python-0.2.1/LICENSES/GPL-2.0-or-later.txt +342 -0
- lme_python-0.2.1/LICENSES/Intel-Simplified-Software-License.txt +79 -0
- lme_python-0.2.1/LICENSES/LGPL-2.1-only.txt +412 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/OPTIMIZATION.md +161 -32
- {lme_python-0.1.9 → lme_python-0.2.1}/PKG-INFO +1 -1
- {lme_python-0.1.9 → lme_python-0.2.1}/README.md +15 -10
- lme_python-0.2.1/RELEASING.md +260 -0
- lme_python-0.2.1/RELINKING.md +22 -0
- lme_python-0.2.1/REPO_COMPLETION_BY_AREA.md +110 -0
- lme_python-0.2.1/THIRD_PARTY_NOTICES.md +18 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/Taskfile.yml +53 -3
- {lme_python-0.1.9 → lme_python-0.2.1}/USABILITY.md +23 -16
- {lme_python-0.1.9 → lme_python-0.2.1}/benches/bench_math.rs +33 -7
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-08.json +82 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-direct-intercept-gram.json +24 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-full-lmm.json +46 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-glmm.json +26 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-large-intercept-setup.json +26 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-large-slopes-linear-cache.json +23 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-large-slopes.json +23 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09-sleepstudy-slopes.json +54 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-09.json +83 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-10-cold-setup-followup.json +24 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-16-cold-fit-lt1.json +363 -0
- lme_python-0.2.1/benchmarks/fair-rust-julia-reference-2026-07-22-full-tier-a.json +1593 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/COMPARISONS.md +31 -4
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/bench_fair_julia_timing.jl +3 -2
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/bench_fair_rust_julia.rs +38 -9
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/bench_perf_breakdown.rs +6 -0
- lme_python-0.2.1/comparisons/nlmm_sspower.R +60 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity_export.rs +1 -6
- lme_python-0.2.1/completion_manifest.json +20 -0
- lme_python-0.2.1/docs/CALO_CALIBRATION.md +124 -0
- lme_python-0.2.1/examples/batch_sspower_cpu.rs +221 -0
- lme_python-0.2.1/examples/dump_cascade_fixtures.rs +339 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/examples/nlmm_fixture_dump.rs +11 -0
- lme_python-0.2.1/legal/dependency-license-exceptions.json +17 -0
- lme_python-0.2.1/legal/fixture-provenance.json +45 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/Cargo.lock +13 -174
- {lme_python-0.1.9 → lme_python-0.2.1}/python/Cargo.toml +1 -1
- {lme_python-0.1.9 → lme_python-0.2.1}/python/PYTHON_GUIDE.md +173 -13
- {lme_python-0.1.9 → lme_python-0.2.1}/python/lme_python.pyi +158 -2
- {lme_python-0.1.9 → lme_python-0.2.1}/python/src/lib.rs +754 -25
- lme_python-0.2.1/python/tests/test_cv.py +102 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/tests/test_golden_parity.py +9 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/tests/test_nlmer_custom_mean.py +25 -0
- lme_python-0.2.1/python/tests/test_simulate_scale.py +43 -0
- lme_python-0.2.1/python/tests/test_wheel_notices.py +86 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/ci/README.md +2 -2
- lme_python-0.2.1/scripts/ci/check_completion_score.py +101 -0
- lme_python-0.2.1/scripts/ci/check_legal_compliance.py +99 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/ci/lme_ci.py +252 -33
- lme_python-0.2.1/scripts/ci/package_wheel_notices.py +165 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/run_fair_rust_julia_benchmark.py +11 -3
- lme_python-0.2.1/src/bootstrap.rs +523 -0
- lme_python-0.2.1/src/cv.rs +720 -0
- lme_python-0.2.1/src/formula.rs +653 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/glmm_math.rs +74 -36
- {lme_python-0.1.9 → lme_python-0.2.1}/src/intercept_blocked.rs +643 -58
- {lme_python-0.1.9 → lme_python-0.2.1}/src/kenward_roger.rs +48 -20
- {lme_python-0.1.9 → lme_python-0.2.1}/src/lib.rs +419 -157
- {lme_python-0.1.9 → lme_python-0.2.1}/src/math.rs +782 -57
- {lme_python-0.1.9 → lme_python-0.2.1}/src/model_matrix.rs +709 -110
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/fit.rs +178 -33
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/formula.rs +57 -4
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/mean.rs +11 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/mean_fn.rs +31 -1
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/mod.rs +20 -3
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/self_start.rs +162 -2
- lme_python-0.2.1/src/nlmm/ssasympoff.rs +46 -0
- lme_python-0.2.1/src/nlmm/ssasymporig.rs +43 -0
- lme_python-0.2.1/src/nlmm/ssbiexp.rs +49 -0
- lme_python-0.2.1/src/nlmm/ssfpl.rs +50 -0
- lme_python-0.2.1/src/nlmm/sspower.rs +45 -0
- lme_python-0.2.1/src/nlmm/ssweibull.rs +53 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/optimizer.rs +97 -13
- {lme_python-0.1.9 → lme_python-0.2.1}/src/perf_diag.rs +2 -1
- lme_python-0.2.1/src/profile_ci.rs +473 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/robust.rs +1 -1
- {lme_python-0.1.9 → lme_python-0.2.1}/src/satterthwaite.rs +1 -0
- lme_python-0.2.1/src/simulate.rs +237 -0
- lme_python-0.2.1/tests/ci_consolidated.rs +102 -0
- lme_python-0.2.1/tests/data/dyestuff_intercept_reml.json +17 -0
- lme_python-0.2.1/tests/data/glmm_binomial_agq.json +9 -0
- lme_python-0.2.1/tests/data/glmm_binomial_cloglog.json +19 -0
- lme_python-0.2.1/tests/data/glmm_gamma_dyestuff.json +15 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/golden_parity_manifest.json +309 -0
- lme_python-0.2.1/tests/data/sleepstudy_confint_profile.json +11 -0
- lme_python-0.2.1/tests/data/ssasympoff_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/ssasympoff_synthetic.csv +61 -0
- lme_python-0.2.1/tests/data/ssasymporig_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/ssasymporig_synthetic.csv +61 -0
- lme_python-0.2.1/tests/data/ssbiexp_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/ssbiexp_synthetic.csv +97 -0
- lme_python-0.2.1/tests/data/ssfpl_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/ssfpl_synthetic.csv +61 -0
- lme_python-0.2.1/tests/data/sspower_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/sspower_synthetic.csv +61 -0
- lme_python-0.2.1/tests/data/ssweibull_nlmer.json +10 -0
- lme_python-0.2.1/tests/data/ssweibull_synthetic.csv +109 -0
- lme_python-0.2.1/tests/generate_nlmm_fixtures.R +343 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/generate_test_data.R +84 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_anova.rs +1 -0
- lme_python-0.2.1/tests/test_bootstrap.rs +316 -0
- lme_python-0.2.1/tests/test_confint_profile.rs +119 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_confint_simulate.rs +71 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_coverage_gaps.rs +1 -0
- lme_python-0.2.1/tests/test_cv.rs +223 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_e2e_lmer.rs +1 -1
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_failure_modes.rs +14 -9
- lme_python-0.2.1/tests/test_formula.rs +19 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_formula_stress.rs +188 -28
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_glmm.rs +10 -3
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_golden_parity.rs +1 -4
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_intercept_only.rs +4 -1
- lme_python-0.2.1/tests/test_nlmm_bounds.rs +153 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_orange.rs +2 -2
- lme_python-0.2.1/tests/test_nlmm_ss_new_means.rs +132 -0
- lme_python-0.2.1/tests/test_nlmm_ssasymp_off_orig.rs +76 -0
- lme_python-0.2.1/tests/test_nlmm_sspower.rs +99 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_statistical_identities.rs +1 -1
- lme_python-0.1.9/.github/workflows/audit.yml +0 -55
- lme_python-0.1.9/.github/workflows/ci.yml +0 -225
- lme_python-0.1.9/.github/workflows/crate-publish-dry-run.yml +0 -28
- lme_python-0.1.9/.github/workflows/python-release.yml +0 -132
- lme_python-0.1.9/AGENTS.md +0 -192
- lme_python-0.1.9/RELEASING.md +0 -247
- lme_python-0.1.9/REPO_COMPLETION_BY_AREA.md +0 -102
- lme_python-0.1.9/scripts/ast_explorations/test_fiasto.rs +0 -6
- lme_python-0.1.9/scripts/ast_explorations/test_fiasto_offset.rs +0 -6
- lme_python-0.1.9/src/formula.rs +0 -372
- lme_python-0.1.9/tests/generate_nlmm_fixtures.R +0 -65
- lme_python-0.1.9/tests/test_formula.rs +0 -11
- {lme_python-0.1.9 → lme_python-0.2.1}/.JuliaFormatter.toml +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/.gitignore +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/LICENSE +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/benches/bench_load_production.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/benchmarks/fair-rust-julia-reference-2026-07-04.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/benchmarks/fair-rust-julia-reference-2026-07-06.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/bench_fair_julia_perf.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/categorical_anova.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/categorical_anova.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/categorical_anova.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/categorical_anova.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/comparison_chart.png +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_cbpp.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_cbpp.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_cbpp.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_cbpp.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_gaussian.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_gaussian.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_gaussian.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_gaussian.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_grouseticks.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_grouseticks.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_grouseticks.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/glmm_grouseticks.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmer_weighted.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmer_weighted.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmer_weighted.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmer_weighted.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_dyestuff.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_dyestuff.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_dyestuff.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_dyestuff.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_pastes.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_pastes.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_pastes.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_pastes.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_penicillin.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_penicillin.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_penicillin.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/lmm_penicillin.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_offset.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_offset.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_probit.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_probit.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_weighted.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/glmm_weighted.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/parity_r_setup.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/sleepstudy_offset.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/parity/sleepstudy_offset.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/r_setup.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy_ml.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy_ml.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy_ml.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/comparisons/sleepstudy_ml.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/docs/benchmarks/app.js +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/docs/benchmarks/index.html +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/docs/benchmarks/styles.css +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/docs/index.html +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/lefthook.yml +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/mise.toml +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/pyproject.toml +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/glmer_cbpp.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/glmer_grouseticks.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/lm_basics.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/lmer_sleepstudy.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/model_comparison.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/.gitignore +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/README.md +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/compare_plots.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/figure_specs.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/find_rscript.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/numeric_overlay.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/paths.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/plot_demo.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/plot_r.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/plotting_demo/run_all.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/README.md +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/conftest.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/parity.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/paths.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/run.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/examples/verification_project/test_parity.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/tests/test_api_parity.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/tests/test_basic.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/tests/test_dataframe_inputs.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/python/uv.lock +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/build_benchmark_site.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/ci/julia_format.jl +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/ci/r_format.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/ci/run.sh +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/dump_dyestuff.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/dump_pastes.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/local_ci.ps1 +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/local_ci.sh +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/make_penicillin_csv.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/plot_comparisons.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/run_cross_language_benchmarks.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/run_perf_breakdown.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/sync_github_repo_metadata.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/scripts/verify_cross_language_parity.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/anova.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/anova_contrasts.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/contrast.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/ddf.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/family.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/kr_modcomp.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/kr_vcov_adj.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/predict.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/re_cov.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/ssasymp.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/ssgompertz.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/sslogis.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/nlmm/ssmicmen.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/src/quadrature.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/categorical_anova_test.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/cbpp_binary.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/cbpp_binary_weighted.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/dyestuff.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/glmm_binomial.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/glmm_binomial_probit.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/glmm_binomial_weighted.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/glmm_poisson.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/glmm_poisson_offset.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/grouseticks.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/intercept_only.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/mock_crossed.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/mock_ml.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/orange.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/orange_nlmer.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/pastes.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/pastes_cask_reml.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/penicillin.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/penicillin.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/random_slopes.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/sleepstudy.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/sleepstudy_offset_reml.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssasymp_synthetic.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssfol_nlmer.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssgompertz_nlmer.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssgompertz_synthetic.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssmicmen_nlmer.json +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/data/ssmicmen_synthetic.csv +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/gen_nlmm_extras.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/generate_mock_data.py +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_anova_types.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_conditional_real.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_contrast.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_coverage_edge_cases.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_crossed_mock.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_edge_cases.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_errors.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_gaps.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_glmm_links.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_glmm_offset_grouseticks.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_glmm_weighted.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_kenward_roger.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_kr_modcomp_pastes.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_ml_optimization.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_agq.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_custom_mean.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_orange_multi_re.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_self_start.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_ssasymp.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_ssfol.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_nlmm_ssmicmen.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_no_intercept.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_numerical_parity.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_predict.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_production_load.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_random_slopes.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_robust.rs +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_sandwich_math.R +0 -0
- {lme_python-0.1.9 → lme_python-0.2.1}/tests/test_satterthwaite.rs +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Security audit
|
|
2
|
+
|
|
3
|
+
# Release CI calls this workflow as a required publication gate.
|
|
4
|
+
# A weekly schedule and workflow_dispatch provide continuous/on-demand audits.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_call:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "17 4 * * 1"
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: audit-${{ github.workflow }}-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
audit:
|
|
21
|
+
name: cargo audit
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
|
|
26
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
27
|
+
with:
|
|
28
|
+
toolchain: stable
|
|
29
|
+
|
|
30
|
+
- name: Install cargo-audit
|
|
31
|
+
uses: taiki-e/install-action@c44f6b046f1c29ae5918b1e0bfdbb2f1813836fd # v2
|
|
32
|
+
with:
|
|
33
|
+
tool: cargo-audit@0.22.1
|
|
34
|
+
|
|
35
|
+
- name: Run cargo audit (root)
|
|
36
|
+
# paste is required by argmin 0.11; RUSTSEC-2024-0436 is informational
|
|
37
|
+
# and has no patched argmin release. Deny every other warning.
|
|
38
|
+
run: cargo audit --deny warnings --ignore RUSTSEC-2024-0436
|
|
39
|
+
|
|
40
|
+
- name: Run cargo audit (python/)
|
|
41
|
+
working-directory: python
|
|
42
|
+
run: cargo audit --deny warnings --ignore RUSTSEC-2024-0436
|
|
43
|
+
|
|
44
|
+
pip-audit:
|
|
45
|
+
name: pip-audit (uv.lock)
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
49
|
+
|
|
50
|
+
- name: Set up uv
|
|
51
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
52
|
+
with:
|
|
53
|
+
python-version: "3.11"
|
|
54
|
+
enable-cache: true
|
|
55
|
+
cache-dependency-glob: "python/uv.lock"
|
|
56
|
+
|
|
57
|
+
- name: pip-audit
|
|
58
|
+
working-directory: python
|
|
59
|
+
run: |
|
|
60
|
+
set -euo pipefail
|
|
61
|
+
uv sync --extra dev --no-install-project
|
|
62
|
+
uv run --no-sync pip-audit
|
|
@@ -29,15 +29,17 @@ jobs:
|
|
|
29
29
|
name: Criterion Benchmarks
|
|
30
30
|
runs-on: ubuntu-latest
|
|
31
31
|
steps:
|
|
32
|
-
- uses: actions/checkout@
|
|
32
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
33
33
|
|
|
34
|
-
- uses: dtolnay/rust-toolchain@stable
|
|
34
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
35
|
+
with:
|
|
36
|
+
toolchain: stable
|
|
35
37
|
|
|
36
38
|
- name: Install OpenBLAS
|
|
37
39
|
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
38
40
|
|
|
39
41
|
- name: Cache cargo registry and build outputs
|
|
40
|
-
uses: actions/cache@
|
|
42
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
41
43
|
with:
|
|
42
44
|
path: |
|
|
43
45
|
~/.cargo/registry
|
|
@@ -55,7 +57,7 @@ jobs:
|
|
|
55
57
|
tar -czf "benchmark-results/criterion-${{ github.sha }}.tar.gz" target/criterion
|
|
56
58
|
|
|
57
59
|
- name: Upload Criterion artifact
|
|
58
|
-
uses: actions/upload-artifact@v7
|
|
60
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
59
61
|
with:
|
|
60
62
|
name: criterion-${{ github.sha }}
|
|
61
63
|
path: benchmark-results/criterion-${{ github.sha }}.tar.gz
|
|
@@ -82,11 +84,13 @@ jobs:
|
|
|
82
84
|
BENCH_REPEATS: ${{ github.event_name == 'workflow_dispatch' && inputs.repeats || '3' }}
|
|
83
85
|
R_LIBS_USER: ${{ github.workspace }}/.r-lib
|
|
84
86
|
steps:
|
|
85
|
-
- uses: actions/checkout@
|
|
87
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
86
88
|
|
|
87
|
-
- uses: dtolnay/rust-toolchain@stable
|
|
89
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
90
|
+
with:
|
|
91
|
+
toolchain: stable
|
|
88
92
|
|
|
89
|
-
- uses: actions/setup-python@
|
|
93
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
90
94
|
with:
|
|
91
95
|
python-version: "3.11"
|
|
92
96
|
|
|
@@ -101,7 +105,7 @@ jobs:
|
|
|
101
105
|
julia --version
|
|
102
106
|
|
|
103
107
|
- name: Cache cargo registry and build outputs
|
|
104
|
-
uses: actions/cache@
|
|
108
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
105
109
|
with:
|
|
106
110
|
path: |
|
|
107
111
|
~/.cargo/registry
|
|
@@ -157,9 +161,10 @@ jobs:
|
|
|
157
161
|
|
|
158
162
|
- name: Upload cross-language artifact
|
|
159
163
|
if: always()
|
|
160
|
-
uses: actions/upload-artifact@v7
|
|
164
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
161
165
|
with:
|
|
162
166
|
name: cross-language-${{ github.sha }}
|
|
167
|
+
if-no-files-found: ignore
|
|
163
168
|
path: |
|
|
164
169
|
benchmark-results/cross-language-${{ github.sha }}.json
|
|
165
170
|
benchmark-results/fair-rust-julia-${{ github.sha }}.json
|
|
@@ -176,9 +181,13 @@ jobs:
|
|
|
176
181
|
gh release create "${GITHUB_REF_NAME}" --title "${GITHUB_REF_NAME}"
|
|
177
182
|
fi
|
|
178
183
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
cross_json="benchmark-results/cross-language-${{ github.sha }}.json"
|
|
185
|
+
fair_json="benchmark-results/fair-rust-julia-${{ github.sha }}.json"
|
|
186
|
+
if [ -f "$cross_json" ]; then
|
|
187
|
+
gh release upload "${GITHUB_REF_NAME}" "$cross_json" --clobber
|
|
188
|
+
fi
|
|
189
|
+
if [ -f "$fair_json" ]; then
|
|
190
|
+
gh release upload "${GITHUB_REF_NAME}" "$fair_json" --clobber
|
|
182
191
|
fi
|
|
183
192
|
|
|
184
193
|
- name: Fail if cross-language benchmarks failed
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Prime Rust caches
|
|
2
|
+
|
|
3
|
+
# PR caches are scoped to a single pull request. Keep trusted default-branch
|
|
4
|
+
# dependency caches warm so new PRs do not start by rebuilding Polars and BLAS.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- master
|
|
10
|
+
paths:
|
|
11
|
+
- "Cargo.toml"
|
|
12
|
+
- "Cargo.lock"
|
|
13
|
+
- "python/Cargo.toml"
|
|
14
|
+
- "python/Cargo.lock"
|
|
15
|
+
- "rust-toolchain"
|
|
16
|
+
- "rust-toolchain.toml"
|
|
17
|
+
- ".cargo/**"
|
|
18
|
+
- ".github/workflows/ci.yml"
|
|
19
|
+
- ".github/workflows/cache-prime.yml"
|
|
20
|
+
schedule:
|
|
21
|
+
- cron: "17 3 * * 1"
|
|
22
|
+
workflow_dispatch:
|
|
23
|
+
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
|
|
27
|
+
concurrency:
|
|
28
|
+
group: cache-prime-${{ github.ref }}
|
|
29
|
+
cancel-in-progress: true
|
|
30
|
+
|
|
31
|
+
env:
|
|
32
|
+
CARGO_TERM_COLOR: always
|
|
33
|
+
CARGO_INCREMENTAL: "0"
|
|
34
|
+
CARGO_PROFILE_DEV_DEBUG: "0"
|
|
35
|
+
CARGO_PROFILE_TEST_DEBUG: "0"
|
|
36
|
+
|
|
37
|
+
jobs:
|
|
38
|
+
rust-dependencies:
|
|
39
|
+
name: Rust dependencies (${{ matrix.os }})
|
|
40
|
+
runs-on: ${{ matrix.os }}
|
|
41
|
+
strategy:
|
|
42
|
+
fail-fast: false
|
|
43
|
+
matrix:
|
|
44
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
47
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
48
|
+
with:
|
|
49
|
+
toolchain: stable
|
|
50
|
+
- name: Install OpenBLAS (Ubuntu)
|
|
51
|
+
if: matrix.os == 'ubuntu-latest'
|
|
52
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
53
|
+
- name: Set OpenBLAS target (macOS)
|
|
54
|
+
if: matrix.os == 'macos-latest'
|
|
55
|
+
run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
|
|
56
|
+
- name: Cache Rust dependencies
|
|
57
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
58
|
+
with:
|
|
59
|
+
shared-key: ci-v2-${{ runner.os }}-rust-test
|
|
60
|
+
cache-workspace-crates: ${{ runner.os != 'Linux' }}
|
|
61
|
+
- name: Compile canonical test dependencies
|
|
62
|
+
if: matrix.os == 'ubuntu-latest'
|
|
63
|
+
run: cargo test --locked --no-run
|
|
64
|
+
- name: Compile consolidated test dependencies
|
|
65
|
+
if: matrix.os != 'ubuntu-latest'
|
|
66
|
+
run: python scripts/ci/lme_ci.py consolidated-test --no-run
|
|
67
|
+
|
|
68
|
+
production-dependencies:
|
|
69
|
+
name: Production-load dependencies (ubuntu)
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
73
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
74
|
+
with:
|
|
75
|
+
toolchain: stable
|
|
76
|
+
- name: Install OpenBLAS
|
|
77
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
78
|
+
- name: Cache production-load Rust dependencies
|
|
79
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
80
|
+
with:
|
|
81
|
+
shared-key: ci-v2-${{ runner.os }}-rust-release
|
|
82
|
+
cache-workspace-crates: true
|
|
83
|
+
- name: Compile production-load dependencies
|
|
84
|
+
run: cargo test --release --locked --test test_production_load --no-run
|
|
85
|
+
|
|
86
|
+
python-dependencies:
|
|
87
|
+
name: Python dependencies (${{ matrix.os }})
|
|
88
|
+
runs-on: ${{ matrix.os }}
|
|
89
|
+
strategy:
|
|
90
|
+
fail-fast: false
|
|
91
|
+
matrix:
|
|
92
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
95
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
96
|
+
with:
|
|
97
|
+
toolchain: stable
|
|
98
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
99
|
+
with:
|
|
100
|
+
python-version: "3.11"
|
|
101
|
+
- name: Install OpenBLAS (Ubuntu)
|
|
102
|
+
if: matrix.os == 'ubuntu-latest'
|
|
103
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
104
|
+
- name: Set OpenBLAS target (macOS)
|
|
105
|
+
if: matrix.os == 'macos-latest'
|
|
106
|
+
run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
|
|
107
|
+
- name: Cache Python Rust dependencies
|
|
108
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
109
|
+
with:
|
|
110
|
+
shared-key: ci-${{ runner.os }}-python
|
|
111
|
+
workspaces: python -> target
|
|
112
|
+
- name: Compile Python binding dependencies
|
|
113
|
+
env:
|
|
114
|
+
PYO3_PYTHON: python
|
|
115
|
+
run: cargo build --release --manifest-path python/Cargo.toml
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Automatic runs: pull requests and v* release tags. Use workflow_dispatch for
|
|
4
|
+
# an intentional full check on any branch (Actions → CI → Run workflow).
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- "v*"
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
env:
|
|
21
|
+
CARGO_TERM_COLOR: always
|
|
22
|
+
CARGO_INCREMENTAL: "0"
|
|
23
|
+
CARGO_PROFILE_DEV_DEBUG: "0"
|
|
24
|
+
CARGO_PROFILE_TEST_DEBUG: "0"
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
release-policy:
|
|
28
|
+
name: Release policy checks
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
32
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.11"
|
|
35
|
+
- name: Validate legal notices and provenance
|
|
36
|
+
run: python3 scripts/ci/lme_ci.py legal
|
|
37
|
+
- name: Validate completion score claims
|
|
38
|
+
run: python3 scripts/ci/lme_ci.py completion-check
|
|
39
|
+
|
|
40
|
+
security-audit:
|
|
41
|
+
name: Dependency security audit
|
|
42
|
+
permissions:
|
|
43
|
+
contents: read
|
|
44
|
+
uses: ./.github/workflows/audit.yml
|
|
45
|
+
|
|
46
|
+
rust-ubuntu:
|
|
47
|
+
name: Rust validation (ubuntu)
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
51
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
52
|
+
with:
|
|
53
|
+
toolchain: stable
|
|
54
|
+
- name: Install OpenBLAS
|
|
55
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
56
|
+
- name: Cache Rust dependencies
|
|
57
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
58
|
+
with:
|
|
59
|
+
shared-key: ci-v2-${{ runner.os }}-rust-test
|
|
60
|
+
save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
|
|
61
|
+
- name: rustfmt --check
|
|
62
|
+
id: rustfmt
|
|
63
|
+
continue-on-error: true
|
|
64
|
+
run: python3 scripts/ci/lme_ci.py fmt-check
|
|
65
|
+
- name: clippy
|
|
66
|
+
id: clippy
|
|
67
|
+
continue-on-error: true
|
|
68
|
+
run: python3 scripts/ci/lme_ci.py clippy
|
|
69
|
+
- name: cargo check --workspace --all-targets
|
|
70
|
+
id: check
|
|
71
|
+
continue-on-error: true
|
|
72
|
+
run: python3 scripts/ci/lme_ci.py check
|
|
73
|
+
- name: Run tests
|
|
74
|
+
id: tests
|
|
75
|
+
continue-on-error: true
|
|
76
|
+
run: python3 scripts/ci/lme_ci.py build-test
|
|
77
|
+
- name: Run doctests
|
|
78
|
+
id: doctests
|
|
79
|
+
continue-on-error: true
|
|
80
|
+
run: python3 scripts/ci/lme_ci.py doctest
|
|
81
|
+
- name: Build documentation
|
|
82
|
+
id: docs
|
|
83
|
+
continue-on-error: true
|
|
84
|
+
run: python3 scripts/ci/lme_ci.py doc
|
|
85
|
+
- name: Report Rust validation failures
|
|
86
|
+
if: >-
|
|
87
|
+
${{ !cancelled() && (
|
|
88
|
+
steps.rustfmt.outcome == 'failure' ||
|
|
89
|
+
steps.clippy.outcome == 'failure' ||
|
|
90
|
+
steps.check.outcome == 'failure' ||
|
|
91
|
+
steps.tests.outcome == 'failure' ||
|
|
92
|
+
steps.doctests.outcome == 'failure' ||
|
|
93
|
+
steps.docs.outcome == 'failure'
|
|
94
|
+
) }}
|
|
95
|
+
run: exit 1
|
|
96
|
+
|
|
97
|
+
test:
|
|
98
|
+
name: Test (${{ matrix.os }})
|
|
99
|
+
runs-on: ${{ matrix.os }}
|
|
100
|
+
strategy:
|
|
101
|
+
fail-fast: false
|
|
102
|
+
matrix:
|
|
103
|
+
os: [windows-latest, macos-latest]
|
|
104
|
+
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
107
|
+
|
|
108
|
+
- name: Install Rust toolchain
|
|
109
|
+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
110
|
+
with:
|
|
111
|
+
toolchain: stable
|
|
112
|
+
|
|
113
|
+
- name: Cache Rust dependencies
|
|
114
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
115
|
+
with:
|
|
116
|
+
shared-key: ci-v2-${{ runner.os }}-rust-test
|
|
117
|
+
cache-workspace-crates: true
|
|
118
|
+
save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
|
|
119
|
+
|
|
120
|
+
- name: Set OpenBLAS target (macOS)
|
|
121
|
+
if: matrix.os == 'macos-latest'
|
|
122
|
+
run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
|
|
123
|
+
|
|
124
|
+
- name: Run tests
|
|
125
|
+
run: python scripts/ci/lme_ci.py consolidated-test
|
|
126
|
+
|
|
127
|
+
production-load:
|
|
128
|
+
name: Production load & perf gates (ubuntu, release)
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
132
|
+
|
|
133
|
+
- name: Install Rust toolchain
|
|
134
|
+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
135
|
+
with:
|
|
136
|
+
toolchain: stable
|
|
137
|
+
|
|
138
|
+
- name: Install OpenBLAS (Ubuntu)
|
|
139
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
140
|
+
|
|
141
|
+
- name: Restore Rust dependencies
|
|
142
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
143
|
+
with:
|
|
144
|
+
shared-key: ci-v2-${{ runner.os }}-rust-release
|
|
145
|
+
cache-workspace-crates: true
|
|
146
|
+
save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
|
|
147
|
+
|
|
148
|
+
- name: Production load tests (smoke + release wall-clock gates)
|
|
149
|
+
run: cargo test --release --locked --verbose --test test_production_load
|
|
150
|
+
|
|
151
|
+
- name: Heavy production load tests (ignored)
|
|
152
|
+
if: github.event_name != 'pull_request'
|
|
153
|
+
run: cargo test --release --locked --verbose --test test_production_load -- --ignored --test-threads=1
|
|
154
|
+
|
|
155
|
+
python-bindings-versions:
|
|
156
|
+
name: Python ${{ matrix.python-version }} (ubuntu)
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
strategy:
|
|
159
|
+
fail-fast: false
|
|
160
|
+
matrix:
|
|
161
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
162
|
+
steps:
|
|
163
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
164
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
165
|
+
with:
|
|
166
|
+
toolchain: stable
|
|
167
|
+
- name: Install OpenBLAS
|
|
168
|
+
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
|
|
169
|
+
- name: Cache Python Rust dependencies
|
|
170
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
171
|
+
with:
|
|
172
|
+
shared-key: ci-${{ runner.os }}-python
|
|
173
|
+
workspaces: python -> target
|
|
174
|
+
save-if: ${{ matrix.python-version == '3.11' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/master') }}
|
|
175
|
+
- name: Set up uv
|
|
176
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
177
|
+
with:
|
|
178
|
+
python-version: ${{ matrix.python-version }}
|
|
179
|
+
enable-cache: true
|
|
180
|
+
cache-dependency-glob: "python/uv.lock"
|
|
181
|
+
|
|
182
|
+
- name: Python bindings (canonical editable identity + isolated wheel)
|
|
183
|
+
if: matrix.python-version == '3.11'
|
|
184
|
+
run: python scripts/ci/lme_ci.py python --python-version ${{ matrix.python-version }}
|
|
185
|
+
|
|
186
|
+
- name: Python bindings (isolated wheel compatibility)
|
|
187
|
+
if: matrix.python-version != '3.11'
|
|
188
|
+
run: python scripts/ci/lme_ci.py python --python-version ${{ matrix.python-version }} --wheel-only
|
|
189
|
+
|
|
190
|
+
python-bindings-os:
|
|
191
|
+
name: Python 3.11 (${{ matrix.os }})
|
|
192
|
+
runs-on: ${{ matrix.os }}
|
|
193
|
+
strategy:
|
|
194
|
+
fail-fast: false
|
|
195
|
+
matrix:
|
|
196
|
+
os: [windows-latest, macos-latest]
|
|
197
|
+
steps:
|
|
198
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
199
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
200
|
+
with:
|
|
201
|
+
toolchain: stable
|
|
202
|
+
- name: Set OpenBLAS target (macOS)
|
|
203
|
+
if: matrix.os == 'macos-latest'
|
|
204
|
+
run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
|
|
205
|
+
- name: Cache Python Rust dependencies
|
|
206
|
+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
207
|
+
with:
|
|
208
|
+
shared-key: ci-${{ runner.os }}-python
|
|
209
|
+
workspaces: python -> target
|
|
210
|
+
save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
|
|
211
|
+
- name: Set up uv
|
|
212
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
213
|
+
with:
|
|
214
|
+
python-version: "3.11"
|
|
215
|
+
enable-cache: true
|
|
216
|
+
cache-dependency-glob: "python/uv.lock"
|
|
217
|
+
- name: Python bindings (isolated wheel OS compatibility)
|
|
218
|
+
run: python scripts/ci/lme_ci.py python --python-version 3.11 --wheel-only
|
|
219
|
+
|
|
220
|
+
publish-crate:
|
|
221
|
+
name: Publish Rust crate after CI
|
|
222
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
223
|
+
needs:
|
|
224
|
+
- release-policy
|
|
225
|
+
- security-audit
|
|
226
|
+
- rust-ubuntu
|
|
227
|
+
- test
|
|
228
|
+
- production-load
|
|
229
|
+
- python-bindings-versions
|
|
230
|
+
- python-bindings-os
|
|
231
|
+
permissions:
|
|
232
|
+
contents: read
|
|
233
|
+
uses: ./.github/workflows/crate-publish-dry-run.yml
|
|
234
|
+
with:
|
|
235
|
+
publish: true
|
|
236
|
+
secrets: inherit
|
|
237
|
+
|
|
238
|
+
publish-python:
|
|
239
|
+
name: Publish Python artifacts after CI
|
|
240
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
241
|
+
needs:
|
|
242
|
+
- release-policy
|
|
243
|
+
- security-audit
|
|
244
|
+
- rust-ubuntu
|
|
245
|
+
- test
|
|
246
|
+
- production-load
|
|
247
|
+
- python-bindings-versions
|
|
248
|
+
- python-bindings-os
|
|
249
|
+
permissions:
|
|
250
|
+
contents: write
|
|
251
|
+
id-token: write
|
|
252
|
+
uses: ./.github/workflows/python-release.yml
|
|
253
|
+
with:
|
|
254
|
+
publish: true
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Publish Rust crate
|
|
2
|
+
|
|
3
|
+
# CI calls this workflow after every release-tag validation job succeeds.
|
|
4
|
+
# Manual dispatch validates with cargo publish --dry-run and never publishes.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_call:
|
|
8
|
+
inputs:
|
|
9
|
+
publish:
|
|
10
|
+
description: Publish the validated release tag to crates.io
|
|
11
|
+
required: false
|
|
12
|
+
type: boolean
|
|
13
|
+
default: false
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: publish-crate-${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
publish:
|
|
25
|
+
name: cargo publish
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
|
|
30
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
|
|
31
|
+
with:
|
|
32
|
+
toolchain: stable
|
|
33
|
+
|
|
34
|
+
- name: Validate crate package (dry run)
|
|
35
|
+
run: cargo publish --dry-run --locked
|
|
36
|
+
|
|
37
|
+
- name: Publish root crate
|
|
38
|
+
if: inputs.publish && startsWith(github.ref, 'refs/tags/v')
|
|
39
|
+
env:
|
|
40
|
+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
41
|
+
run: |
|
|
42
|
+
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
|
43
|
+
if cargo search lme-rs --limit 1 2>/dev/null | grep -q "= \"$VERSION\""; then
|
|
44
|
+
echo "lme-rs $VERSION already on crates.io; skipping publish."
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
test -n "$CARGO_REGISTRY_TOKEN" || { echo "CARGO_REGISTRY_TOKEN repository secret is required to publish a new version" >&2; exit 1; }
|
|
48
|
+
cargo publish --locked
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
#
|
|
2
|
-
name: Fuzz
|
|
1
|
+
# Weekly and manually dispatched libFuzzer smoke.
|
|
2
|
+
name: Fuzz smoke
|
|
3
3
|
|
|
4
4
|
on:
|
|
5
5
|
workflow_dispatch:
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: "43 3 * * 0"
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: fuzz-${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
6
15
|
|
|
7
16
|
jobs:
|
|
8
17
|
libfuzzer-smoke:
|
|
@@ -13,14 +22,16 @@ jobs:
|
|
|
13
22
|
working-directory: fuzz
|
|
14
23
|
|
|
15
24
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
26
|
|
|
18
|
-
- uses: dtolnay/rust-toolchain@nightly
|
|
27
|
+
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # nightly
|
|
28
|
+
with:
|
|
29
|
+
toolchain: nightly
|
|
19
30
|
|
|
20
31
|
- name: Install cargo-fuzz
|
|
21
|
-
run: cargo install cargo-fuzz --locked
|
|
32
|
+
run: cargo install cargo-fuzz@0.13.2 --locked
|
|
22
33
|
|
|
23
|
-
- uses: Swatinem/rust-cache@v2
|
|
34
|
+
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
24
35
|
with:
|
|
25
36
|
workspaces: fuzz
|
|
26
37
|
|