mixedlm-rs
lmer for Python.
Linear mixed-effects models with lme4 speed, the statsmodels API, and no R required.
Beta — 0.1.0, first release. The numerics are checked hard: the fits agree with
lme4's published results to six decimals, and every claim in this README is tied to a recorded experiment. What is not settled is the surface area. This fits linear mixed models with one grouping factor — no crossed or nested random effects, no variance components, no GLMMs — and it provides no Kenward–Roger or Satterthwaite small-sample corrections. Read docs/LIMITATIONS.md before depending on it for published inference.
What this is for
You measured the same subjects more than once. Or students inside classrooms, patients inside clinics, plots inside sites, trials inside people. The observations are not independent, and a plain regression will tell you things that are not true.
Mixed-effects models are the standard answer, and they are the workhorse of experimental science — clinical trials, psychology, neuroscience, ecology, linguistics, education research, pharmacology.
Python's implementation has been the weak link. This is a drop-in replacement for it.
Not on PyPI yet. Build it from a checkout — you need a Rust toolchain:
git clone https://github.com/Fatin-Ishraq/mixedlm-rs
cd mixedlm-rs
pip install maturin && maturin build --release --out dist
pip install --find-links dist mixedlm-rs
The build is abi3, so one wheel per platform will cover Python 3.10–3.14 once
these are published, and there will be nothing to compile.
Currently verified: the full suite runs in CI on Linux, macOS and Windows against Python 3.10 through 3.14, plus the exact declared dependency floors on 3.10 and the minimum supported Rust version. Every wheel this project publishes is installed into a clean environment outside the source tree and used to fit a model there, on a runner of its own architecture — including Intel macOS and ARM64 Linux, which the ordinary matrix does not cover. A wheel rebuilt from the unpacked sdist gets the same treatment. The CI badge above is the live answer for the current commit.
Not verified: any platform CI does not run — 32-bit, musl, and any architecture outside the five wheels listed above.
Runs as-is after pip install — no data file to fetch. Eighteen subjects,
each measured over ten days, each with their own intercept and slope:
import numpy as np
import pandas as pd
import mixedlm_rs as mlm
rng = np.random.default_rng(0)
subjects, days = 18, 10
subject = np.repeat(np.arange(subjects), days)
day = np.tile(np.arange(days), subjects)
# Each subject gets their own baseline and their own rate of change.
intercept = rng.normal(250, 25, subjects)[subject]
slope = rng.normal(10, 6, subjects)[subject]
reaction = intercept + slope * day + rng.normal(0, 25, subjects * days)
sleep = pd.DataFrame({"Reaction": reaction, "Days": day, "Subject": subject})
model = mlm.mixedlm("Reaction ~ Days", sleep,
groups=sleep["Subject"], # each subject measured 10 times
re_formula="~Days") # and each has their own slope
result = model.fit()
print(result.summary())
print(f"\nfixed effects: {result.fe_params}")
print(f"converged: {result.converged}")
The same model on lme4's sleepstudy — the dataset this example imitates
— reproduces lme4's published fit to six decimals. That CSV is GPL-2 and is
not shipped with the package (see data/README.md); with a copy
in hand it is pd.read_csv("sleepstudy.csv") in place of the frame above, and
the fit is the one shown below.
Mixed Linear Model Regression Results
==============================================================================
Model: MixedLM Dependent Variable: Reaction
No. Observations: 180 Method: REML
No. Groups: 18 Scale: 654.9410
Min. group size: 10 Log-Likelihood: -871.8141
Max. group size: 10 Converged: Yes
Mean group size: 10.0 Singular fit: No
------------------------------------------------------------------------------
Coef. Std.Err. z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
Intercept 251.405 6.825 36.838 0.000 238.029 264.781
Days 10.467 1.546 6.771 0.000 7.438 13.497
Group Var 612.090 11.881
Group x Days Cov 9.604 1.821
Days Var 35.072 0.610
==============================================================================
lme4 reports this fit as sd(Intercept) = 24.741, sd(Days) = 5.922,
corr = 0.066, sd(Residual) = 25.592, REML criterion 1743.6284. Squaring
those standard deviations gives 612.12 and 35.07, and the criterion is
-2 x -871.8141 = 1743.6282. The variance rows are printed on the same scale
statsmodels prints them, so the two summaries are directly comparable.
Already using statsmodels?
For most code, changing the import is the whole migration.
- from statsmodels.regression.mixed_linear_model import MixedLM
+ from mixedlm_rs import MixedLM
Same classes, same params packing, same summary() layout. The
arguments match too, with the exceptions catalogued in
docs/COMPATIBILITY.md: a few statsmodels
arguments are accepted and warned about rather than honoured, and some
attributes are plain arrays where statsmodels returns a DataFrame.
Three things decide whether that holds for you, and it is worth two minutes to check rather than finding out later:
- One grouping factor. Crossed or nested random effects — two
(...|...)terms — are not supported and raise. This is the biggest gap in the package. - Result containers are ndarrays, not Series.
result.fe_params["x"]raises;result.fe_params[1]works. Useparams_labelledorparam_namesfor name-based access. - Some methods are absent, including
summary().tables/.as_html(),wald_test_terms,t_test_pairwiseand thebsejacfamily.
Everything else — every attribute, every type difference, every method that raises and why — is enumerated in the compatibility contract, which was produced by diffing the two results objects rather than from memory.
If you cannot edit the code that imports it — someone else's library, a notebook you were handed:
import mixedlm_rs
mixedlm_rs.install() # before anything imports statsmodels' MixedLM
import statsmodels.api as sm # sm.MixedLM is now ours
import statsmodels.formula.api as smf # smf.mixedlm is now ours
install() aliases only the mixed-model entry points. statsmodels does far
more than mixed models, and the rest of it is left untouched.
It is not just faster. It is more often right.
This is the part that matters more than the speed.
statsmodels.MixedLM does not merely take a long time — on ordinary inputs it
fails to converge and returns estimates anyway, after retrying bfgs, then
lbfgs, then cg, and giving up with a gradient norm in the hundreds.
When that happens, a researcher either does not notice, or starts deleting random-effects terms until the fit converges. That second response is a documented source of anti-conservative p-values — the "keep it maximal" literature in psycholinguistics exists because of exactly this.
Across 120 randomised fixtures, comparing against statsmodels:
| outcome | count |
|---|---|
| statsmodels did not converge | 26 |
| mixedlm-rs found a strictly better optimum | 42 |
| same optimum | 52 |
| mixedlm-rs found a worse optimum | 0 |
On 56.7% of fixtures the reference either failed or landed somewhere worse.
Reproduce the counts with python bench/differential_table.py.
These are deliberately difficult fixtures — that is what they are for — so the rate is not an estimate of how often statsmodels fails on ordinary published datasets, and should not be read as one.
Singular fits — a variance component genuinely at zero — are reported as
converged, because a boundary optimum is a converged fit. That is what stops
people from mangling their model to silence a warning. They are also flagged
separately, as results.singular, because the estimate being legitimate does
not make the usual Wald intervals around it legitimate: at the boundary the
sampling distribution of a variance parameter is degenerate, and bse_re
returns NaN there rather than a number that would be read as a standard error.
lme4 draws the same distinction with isSingular.
Convergence is certified, not reported. The optimiser's own success flag is never taken as the answer: it says its termination rule fired, not that the point is stationary. The projected gradient is checked against a tolerance that does not depend on the units, and a failed check triggers a restart rather than a warning.
Speed
| n | groups | statsmodels | mixedlm-rs | |
|---|---|---|---|---|
| 10,000 | 500 | 1.65 s | 0.009 s | 183x |
| 40,000 | 5,000 | 11.02 s | 0.017 s | 661x |
| 100,000 | 20,000 | 41.87 s | 0.038 s | 1092x |
| 200,000 | 50,000 | 102.79 s | 0.073 s | 1404x |
| 500,264 | 125,066 | — | 0.218 s |
Re-measured on 2026-09-10 for this release; earlier revisions of this table
published higher speedups (218x / 870x / 1454x / 1836x) that no longer
reproduce. Running the original bench/scaling.py on the same machine today
gives 161x / 598x / 1078x / 1370x, and the recorded run above gives 183x / 661x
/ 1092x / 1404x — the two agree within 12%, and both disagree with what was
published. statsmodels is simply faster now than when those figures were taken;
what changed between the two recordings is not established, so the old numbers
are treated as superseded rather than explained.
Agreement is enforced, not reported: the benchmark aborts rather than print a timing if the fixed effects differ by more than 0.05 of a standard error, the variance components by more than 2%, or our criterion falls below the reference's. On every row above it does not — the largest fixed-effect difference is 3.8e-05 standard errors, and our log-likelihood is never lower.
That last row matches the size reported in
statsmodels#9097 —
125,066 groups — where a user reported waiting 41 minutes for a fit that R's
lmer did in 1–2 seconds. To be clear about what that is and is not: the 41
minutes is their report on their own data, not a measurement made here. This
row is synthetic data at the same group count, so it shows that the size is not
the obstacle. It is not a reproduction of their categorical-design dataset, and
should not be read as a measured 41-minutes-to-0.18-seconds result.
Faster than lme4 itself
statsmodels is what this replaces, but lme4 in R is the strongest
implementation in the market, and pymer4 — which calls lme4 through rpy2 —
is the only way a Python user gets genuine lme4 results today. Same models,
byte-identical data:
| n | groups | mixedlm-rs | lme4 (R) | pymer4 | vs lme4 | vs pymer4 |
|---|---|---|---|---|---|---|
| 10,000 | 500 | 0.010 s | 0.080 s | 1.71 s | 8x | 166x |
| 40,000 | 5,000 | 0.017 s | 0.330 s | 11.67 s | 19x | 683x |
| 100,000 | 20,000 | 0.038 s | 1.120 s | 118.10 s | 30x | 3,127x |
| 200,000 | 50,000 | 0.078 s | 2.510 s | 747.28 s | 32x | 9,554x |
| 500,264 | 125,066 | 0.169 s | 7.330 s | — | 43x | — |
Every figure in these tables is recorded in bench/performance.json with the
commit, machine, repetition count and thread settings that produced it; the
lme4 and pymer4 columns are historical, from a machine with R, and were
not re-measured on this build. See docs/BENCHMARKS.md.
The log-likelihood matches lme4 to six decimals on every fixture. Same
answer, 8–43x faster, and the margin widens with the group count.
pymer4 is lme4, so the gap between those two columns is what a Python
caller pays on top of the fit — and it compounds: 21x at 10,000 rows, 298x at
200,000, where 2.51 s of the 747.28 s is the lmer fit. The remaining 744.77 s
is not a measurement of marshalling alone: pymer4 also runs lmerTest for
Satterthwaite degrees of freedom and extracts the results as R objects, and the
benchmark does not separate those from serialisation. It also still needs R,
Rtools and a writable R library wherever your code runs.
Full tables and caveats →
Where the win comes from — honestly. The largest single factor is structural, not the language:
| step | multiplier |
|---|---|
| profiled REML — upper bound only | 1.7x |
| + batched block-diagonal Cholesky | 30.8x |
| + Rust core | 14.6x |
| + analytic gradient | 2.8x |
| end to end, like for like | 182x |
That last row compares the public API against statsmodels on the same
DataFrame, both parsing a formula, fitting, and computing inference. An earlier
version of this table published 1844x for the same row, which was not a
like-for-like comparison: it measured the bare Rust objective against
statsmodels doing all of that extra work. What was wrong, in
detail →
The formulation is lme4's: eliminate the fixed effects and sigma^2
analytically so the optimiser sees only the 1–3 covariance parameters, and
factorise the block-diagonal penalised system instead of applying a dense
Sherman-Morrison-Woodbury update per group per iteration. Stages 1 and 2 are
reproducible by anyone in NumPy — proto/preml.py is that implementation, in
about 200 lines. Full tables →
The optimiser uses a gradient; lme4's does not
lme4 and MixedModels.jl both optimise the covariance parameters
derivative-free (BOBYQA). Here the analytic gradient of the profiled REML
criterion is evaluated alongside the criterion itself and handed to L-BFGS-B,
which cuts objective evaluations from 44–64 to 11–13 on the benchmark
fixtures.
Two caveats worth stating plainly. The gradient of the profiled criterion is
not new — Bates et al. derive the ML version in the lme4 paper (eq. 46–48), and
MixedModels.jl documents derivative support; what is here is a REML gradient
specialised to the block structure, computed in the passes that already produce
the criterion. And the 44–64 figure is this package's own finite-difference
stage, not BOBYQA: no claim is made about lme4's evaluation count, which was
not measured.
Because a wrong gradient does not crash — it converges quietly to the wrong answer — it is checked against central finite differences over the full product of random-effect count, fixed-effect count and criterion, and at the variance-zero boundary. The derivation →
What is included
| Models | MixedLM, MixedLM.from_formula, mixedlm |
| Results | fe_params, cov_re, cov_re_unscaled, scale, params, bse, bse_fe, bse_re, bse_cov_re, tvalues, pvalues, llf, aic, bic, df_resid, random_effects, random_effects_cov, fittedvalues, resid, conf_int, cov_params, predict, summary, converged, singular |
| Tests | t_test, wald_test, f_test (fixed effects) |
| Persistence | pickling, save / load |
| Parameters | MixedLMParams with from_packed / get_packed / from_components |
| Criteria | REML (default) and ML |
| Aliasing | install() / uninstall() |
Scoped to one grouping factor. Crossed and nested random effects
(vc_formula) break the block-diagonal structure this is built on and need a
sparse Cholesky with a fill-reducing ordering — that is the next release. They
raise NotImplementedError rather than silently fitting a different model, as
do fe_pen, cov_pen and free. GLMMs are out of scope.
Every gap, stated plainly →
Is it actually the same?
That is the only question that matters for a drop-in, so it is what the test
suite is built around — 696 Python tests and 7 Rust tests, with
statsmodels, mypy and the lme4 fixtures installed. Fewer are collected
without them: the differential comparisons skip at import, so a minimal
environment collects 398 rather than skipping 178.
The primary oracle is lme4's published fits, not statsmodels, because
statsmodels is the thing that is wrong on some inputs. sleepstudy, Dyestuff
and the singular Dyestuff2 are reproduced to every published digit, under both
REML and ML.
A further 400-case adversarial sweep — tiny groups, extreme imbalance,
predictors spanning six orders of magnitude, near-collinear fixed effects,
heavy outliers — raised zero exceptions, and found a better optimum than
statsmodels 131 times against 3 losses. Those three are near-ties, worse by
2.7e-06, 5.6e-05 and 5.7e-05 in deviance on a criterion whose own scale is in
the hundreds, and they are reported as losses rather than explained away. One
case of 400 could not be certified as a stationary point, and says so. The sweep is committed as bench/stress_sweep.py, so the classification
can be checked.
Testing found real defects, and they are listed rather than quietly fixed. Differential testing against statsmodels found four during development:
fittedvaluesreturned the marginal fit. statsmodels' is the conditional fit, including the random effects.theta = 0is a stationary point for any data whatsoever. AtLambda = 0every term of the gradient vanishes identically, so a gradient-based optimiser that reaches the bound stops there and reports success — even when the true optimum is an ordinary non-zero variance. Fixed by probing away from the bound and restarting.- That probe ladder was then too coarse. Its smallest step was 0.05, so a
true optimum at
theta = 0.028was still missed — every probe overshot it. - Unidentifiable models were fitted silently. Now detected — though the original reasoning for the check was itself wrong, and the correction is below.
An external review then found several more, which are fixed and documented:
- Catastrophic cancellation in the residual sum of squares. The criterion
was computed as
y'y - beta'X'y - u'Lambda'Z'y, a difference of large nearly equal quantities. With a response around 1e8 — prices in minor units, epoch timestamps, populations — the fit returned a confidently converged wrong answer. The response is now offset by its OLS fit before any cross-product is formed, which makes results invariant to response translation. - Convergence was
optimiser_flag or stationary. A loose tolerance let the optimiser's own success flag overrule the gradient check, reporting success at a projected gradient of 19. Stationarity is now the only test, and it drives a retry rather than just annotating the answer. summary()printed the wrong quantity. It labelledcov_re_unscaledas "Group Var" — 0.935 onsleepstudywhere both lme4 and statsmodels report 612.1.random_effects_covreturned the population covariance for every group, where the conditional covariance given that group's data was asked for.- Malformed input to the compiled core killed the process. An empty or
oversized
thetareached unchecked indexing, andpanic="abort"turned that into a process abort rather than a catchable error. - The identifiability rule was wrong in both directions.
n <= q*mneither implies a divergent likelihood nor catches a confounded single group. The check now measures whether the criterion is flat instead of counting.
What is verified, and every divergence →
Building from source
Needs a Rust toolchain — 1.83 or newer, which is what the locked dependencies require and what CI builds with.
pip install maturin
python -m maturin build --release --out dist
pip install --force-reinstall --no-deps --no-index --find-links dist mixedlm-rs
Development
pip install maturin pytest ruff mypy numpy scipy pandas patsy statsmodels
python -m maturin build --release --out dist
pip install --force-reinstall --no-deps --no-index --find-links dist mixedlm-rs
pytest tests/ -q # the suite
cargo test --lib # the linear algebra and the optimiser
ruff check . # rules pinned in pyproject.toml
mypy # configured in pyproject.toml
cargo clippy --all-targets -- -D warnings
cargo audit # Rust advisories
python -m pip_audit --requirement requirements-runtime.txt
Benchmarks and the recorded numerical baseline:
python bench/scaling.py # scaling against statsmodels
python bench/stages.py # where the speed comes from
python bench/stress_sweep.py # 400 adversarial cases
python bench/baseline.py # re-record bench/baseline.json
Every benchmark refuses to print a timing unless the fits agree; the
tolerances and the reasoning behind each are in bench/tolerances.py. The
counts quoted in the documentation come from bench/baseline.json and are
checked against it by tests/test_baseline.py, so a stale table fails the
suite.
Support
Only the latest release is supported; before 1.0 there are no backports. See SECURITY.md for the reporting process and the dependency-audit policy, and THIRD-PARTY-NOTICES.md for what is linked, what is depended on, and what is deliberately not distributed.
- Issues and questions: https://github.com/Fatin-Ishraq/mixedlm-rs/issues
- Changelog: CHANGELOG.md
- Migration contract: docs/COMPATIBILITY.md
- Known gaps: docs/LIMITATIONS.md
Licence and credit
MIT.
The algorithm is Douglas Bates and colleagues'. This package implements the formulation published in:
Bates, D., Mächler, M., Bolker, B., & Walker, S. (2015). Fitting Linear Mixed-Effects Models Using lme4. Journal of Statistical Software, 67(1), 1–48.
The API mirrors statsmodels (BSD-3), by the statsmodels developers.
The lme4 datasets used to verify correctness (sleepstudy, Dyestuff,
Dyestuff2 and others) are GPL-2 and live in data/ as test fixtures only.
They are excluded from both distributed artifacts — neither the wheel nor the
source archive contains them, so nothing GPL-2 is redistributed under this
project's MIT licence. They are present in the git repository, and the tests
that use them skip when they are absent. See data/README.md.
Metadata
Release files for mixedlm-rs 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mixedlm_rs-0.1.0.tar.gz | 272.4 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| mixedlm_rs-0.1.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| mixedlm_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| mixedlm_rs-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 2.0 MB
Release files / mixedlm_rs-0.1.0.tar.gz
| Download URL | mixedlm_rs-0.1.0.tar.gz |
|---|---|
| Size | 272.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a0ba0eaab77a3efb6204de67c212a4d171634d92a571495ab59687786c4654f1
|
|
BLAKE2b-256 checksum How to use checksums |
a3b01e81d5268fa67b915c7b0a5b5710d94e75ae6814bbea715064cba4a596a4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / mixedlm_rs-0.1.0-cp310-abi3-win_amd64.whl
| Download URL | mixedlm_rs-0.1.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 256.6 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
c6590e05bcd288f19803bcc3563f1731a62bad5a0931658d706f9c070cb9897b
|
|
BLAKE2b-256 checksum How to use checksums |
af148cb1752d8ccb66264a3ddcda8a4c306f08e7129b3efd830bf318924552c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 391.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4679250b7180ebcd3230e21cfc75a2d84af0f438cb56832e30931ff1783fedc7
|
|
BLAKE2b-256 checksum How to use checksums |
2524bd83823a27083aac1d9ad1ace73702fd118edc8031c5ff7c50be938381a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | mixedlm_rs-0.1.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 389.5 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
2d184416883b269f3fca33edd4b3360428cd9d9fbb60285c78cf5c8c9e08e58a
|
|
BLAKE2b-256 checksum How to use checksums |
091ffb6a8ed046f668664a5607f2bbb12b1c0e2f0af178f56ec72a2f2a866bdd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / mixedlm_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | mixedlm_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 352.2 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
d1aff7879d5e0ea637d515f97d7d5fb69dbb85c0d2a2332cb0ead2eca7deb1d5
|
|
BLAKE2b-256 checksum How to use checksums |
9720328e8cc47841030a069155891a5d161a7bc52a2c1f10bec51b6cc0930a1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / mixedlm_rs-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | mixedlm_rs-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 361.8 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
6a618678695844346522117c1f8d3e5569b1fc17165ba8eab72dbbd543c4fcf5
|
|
BLAKE2b-256 checksum How to use checksums |
ccbf0385eb5c80b68cf7fc67c7c3a726728a1d6b97e851fa2c72ef0b2ea6871e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency log