mgcv_rust
A Rust port of R's mgcv package — Generalized Additive Models with automatic smoothing-parameter selection (REML / LAML) and PIRLS fitting — with first-class Python bindings.
The numerical core targets byte-for-byte parity with mgcv on common families, and the Python API is designed to feel like sklearn: a single Gam class, named-predictor DataFrame inputs, fit() / predict() / score(), posterior CI, and subset views for marginal analysis.
| Latest release | 0.11.0 |
| Parity | 554 / 0 / 0 on the mgcv comparison battery |
| Python tests | 211 passed, 1 xfailed |
| Headline perf | 2d_gaussian_additive_n50000_k15_cr — 394 ms → 97 ms (4.05× vs. mgcv) |
| Python wrapper | mgcv_rust.Gam (canonical), GAMFitter deprecated alias |
Why another GAM library?
- R-equivalent answers, Python ergonomics. If you have R /
mgcvusers producing models and Python services consuming them, this gives both sides the same numbers from the same fit. Theserialize()method produces a portable artefact for deployment. - Fast. Aggregate time across 80 parity fixtures: 2.0 s. On the largest Gaussian fixture (
n=50,000,k=15),mgcv_rustis ~4× faster than R'smgcv. - Real CIs, paired diffs.
predict_ci(X)returns(mean, lo, hi)so you never have to "+= intercept" by hand.predict_diff(from_X, to_X, level=...)gives a paired-posterior CI for the difference between two predictions — strictly tighter than the naivepredict_cidifference. - Frozen serving view.
GamPredictor(gam)is an__slots__-locked, inference-only wrapper with strict input validation (feature_names_in_enforcement) and acheck_against(gam, X_sample)round-trip assertion for deployment safety.
Installation
The Python package is built from this repo via maturin:
# Clone, then in a venv:
pip install maturin
maturin develop --features python,blas,blas-system --release
After that, import mgcv_rust works.
For a Rust-only consumer, add to your Cargo.toml:
[dependencies]
mgcv_rust = { git = "https://github.com/AlekJaworski/nn_exploring" }
Quick start
import numpy as np
import pandas as pd
from mgcv_rust import Gam
rng = np.random.default_rng(0)
n = 500
X = pd.DataFrame({
"x0": rng.uniform(-2, 2, n),
"x1": rng.uniform(0, 5, n),
})
y = np.sin(X["x0"]) + 0.3 * (X["x1"] - 2.5)**2 + rng.normal(0, 0.1, n)
gam = Gam(family="gaussian").fit(X, y)
gam.predict(X[:5]) # response-scale predictions
mean, lo, hi = gam.predict_ci(X[:5]) # 95% CI, response scale
gam.score(X, y) # adjusted R²
print(gam.summary()) # mgcv-style block
That's it for the simple case. Read on for the curated tour, or jump
to docs/GETTING_STARTED.md for a
step-by-step tutorial with worked examples.
Tour
1. Build the model
Gam() accepts pandas / polars / numpy. If you pass a DataFrame, the column names become the predictor names; otherwise you can pass them explicitly.
gam = Gam(
family="gaussian", # gaussian, binomial, poisson, gamma, tweedie, nb, t-dist, scat, ...
link=None, # None → canonical link for the family
k_default=10, # default basis dimension per smooth (mgcv default)
term_k_mapping={"x0": 25}, # per-predictor overrides
method="REML",
)
gam.fit(X, y)
After fit, sklearn-style attributes are populated:
gam.coef_ # full β vector (intercept first)
gam.intercept_ # link-scale
gam.intercept_response_ # response-scale (= mean(y) for identity link)
gam.feature_names_in_ # predictor names, fitting order
gam.n_features_in_
gam.lambda_ # per-smooth smoothing parameter
gam.edf_ # per-smooth effective degrees of freedom
gam.k_, gam.bs_ # basis dimension / basis type per smooth
gam.vcov_ # posterior covariance of β̂
2. Predict on different scales
gam.predict(X) # response (default — same as mgcv predict(type="response"))
gam.predict(X, scale="link") # linear predictor, no inverse link (mgcv type="link")
result = gam.predict(X, type="terms") # decomposition
result.intercept # scalar, link scale
result.contributions # DataFrame (n × m_smooths), link-scale, centered on training
result.total # response-scale ≡ gam.predict(X)
Invariant: gam.predict(X) == inv_link(intercept + result.contributions.sum(axis=1)).
3. Confidence intervals
mean, lo, hi = gam.predict_ci(X, level=0.95) # response, 95% CI
mean, lo, hi = gam.predict_ci(X, scale="link") # link-scale CI
mean, lo, hi = gam.predict_ci(X, level=0.5) # 50% CI (narrower)
mean matches gam.predict(X, scale=scale) exactly. The CI is built from n_samples (default 1000) draws of β ~ N(β̂, vcov).
The legacy predict_ci(X, alpha=0.05) → (lo, hi) form still works (emits a DeprecationWarning) so existing callers don't break.
4. Differences between predictions, with paired CI
# Per-row diff: to[i] - from[i]
diff = gam.predict_diff(from_X, to_X)
# With paired posterior CI — much narrower than predict_ci differences
diff, lo, hi = gam.predict_diff(from_X, to_X, level=0.95)
# One row broadcast against many
diff = gam.predict_diff(baseline_row, candidates, broadcast="from")
diff = gam.predict_diff(candidates, target_row, broadcast="to")
Identity-link only — for non-identity links the response-scale difference isn't linear in β, so the closed-form CI argument doesn't transfer.
5. Subset / marginal views
gam[name] returns a view that includes only the listed smooths (and optionally the intercept). All predict methods inherit it.
gam[["x0"]].predict(X) # marginal effect of x0, response scale
gam[["x0"]].predict(X, scale="deviation") # link-scale, intercept zeroed (sum-to-zero on train)
gam[["x0", Gam.INTERCEPT]].predict(X) # marginal effect + intercept
gam[["x0"]].partial_effect("x0").plot() # what the smooth looks like
All sklearn attributes filter to the active features:
gam[["x0"]].coef_ # just the x0 block (+ intercept if active)
gam[["x0"]].feature_names_in_ # ["x0"]
6. Plotting, summary, score
gam.plot() # figure with one subplot per smooth (CI bands shaded)
gam.plot("x0") # single-smooth axes
df = gam.partial_effect("x0", level=0.95) # underlying data: columns x0, effect, lo, hi
print(gam.summary())
# Gam summary family=gaussian link=identity n_obs=500
# intercept (link) = -0.0123
# intercept (response) = -0.0123
# scale (σ²) = 0.0101
# deviance = 4.8732
# R² (adj) = 0.9612
# smooths:
# s( x0) k= 10 edf= 6.13 λ=2.345e-02
# s( x1) k= 10 edf= 3.07 λ=4.890e-01
gam.score(X, y) # adjusted R² for regression; accuracy@0.5 for binomial
gam.predict_proba(X) # binomial only: (n, 2) [[P(0), P(1)]]
7. Serving with GamPredictor
For deployment paths, wrap the fitted Gam in a GamPredictor. Same API surface, plus strict column validation and a round-trip assertion.
from mgcv_rust import GamPredictor
predictor = GamPredictor(gam)
predictor.check_against(gam, X[:50]) # raises if predictions diverge
predictor.predict(X_serve) # ValueError if any expected column is missing
predictor[["x0"]].predict(X_serve) # subset view returns another GamPredictor
# `__slots__` blocks attribute leaks — once built, the bound Gam's
# coef/vcov/schema are the contract.
This structurally closes two production bug classes:
- Column index drift when the serving DataFrame's columns differ from training:
feature_names_in_is enforced on everypredictcall (re-ordered → realigned; missing →ValueError). - x-grid clamping in interpolation-based predictors:
GamPredictorrecomputes the basis at the requested X viaevaluate_lpmatrix, so there's no pre-computed grid to clamp against.
Families and links
| Family | Default link | Other links | Notes |
|---|---|---|---|
gaussian |
identity | — | bs-spline / cubic-regression / random-effects bases supported |
binomial |
logit | — | predict_proba() available |
poisson |
log | — | |
gamma |
inverse | log |
log-link via link="log" |
tweedie |
log | — | tweedie_p= (default 1.5); fixed-p |
nb / negbin |
log | — | nb profiles θ; negbin is fixed-θ |
t-dist / scat |
identity | — | df profiled if not given (df ∈ [2, 100]) |
quasipoisson, quasibinomial |
log / logit | — | dispersion-aware |
quantile |
identity | — | see mgcv_rust.fit_quantile / fit_quantile_lss; OOS presets documented in docs/qgam_oos_presets.md |
Architecture (Rust side)
| File | Responsibility |
|---|---|
src/gam.rs |
GAM struct + fit / predict entry points |
src/pirls.rs |
Penalized IRLS inner loop |
src/reml/ |
Outer-loop REML / LAML optimization |
src/smooth.rs |
Basis functions (cubic-regression, B-spline, random effects, tensor products) |
src/penalty.rs |
Penalty-matrix construction |
src/lib.rs |
PyO3 bindings — PyGAM, compute_penalty_matrix, newton_pirls_py |
Build features:
python— enable PyO3 bindings.blas/blas-system— link against system BLAS for matmul-heavy paths.
Parity and performance
Run the parity battery against R/mgcv:
pytest tests/parity/ -q
# 554 passed, 0 failed, 0 xfailed, 0 skipped
Microbench:
python3 scripts/python/bench_step_blend.py 5
Headline (2d_gaussian_additive_n50000_k15_cr, identity link):
| Time | |
|---|---|
R mgcv |
~394 ms |
mgcv_rust 0.11.0 |
97 ms |
Status and limitations
- Joint
(ρ, log φ)outer Newton not yet implemented — the binding constraint for closing the remaining performance gap on dispersion-bearing GLMs. Tracked inmgcv_rust - Backlog - Next Numerical Steps(Obsidian). predict_diffis identity-link only; non-identity raises with a workaround pointing atget_posterior_samples.- Auto-
ktuning is opt-in viaGam(auto_k=True). Default is a single fit atk_default=10(mgcv's default), withterm_k_mappingoverrides — closer to mgcv's "tune k, run k.check" convention and avoids hidden multi-fit costs. - sklearn
BaseEstimatormixin (forPipeline/GridSearchCV) is not yet wrapped — soft-dep, deferred.
References
- Wood, S.N. (2017). Generalized Additive Models: An Introduction with R (2nd ed.). Chapman and Hall/CRC.
- Wood, S.N. (2011). Fast stable restricted maximum likelihood and marginal likelihood estimation of semiparametric generalized linear models. J. R. Stat. Soc. B, 73(1), 3–36.
License
MIT — see LICENSE.
Metadata
Release files for mgcv-rust 0.23.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mgcv_rust-0.23.2.tar.gz | 14.3 MB | Without provenance | Details |
Built distributions (wheels)
Total release size: 44.8 MB
Release files / mgcv_rust-0.23.2.tar.gz
| Download URL | mgcv_rust-0.23.2.tar.gz |
|---|---|
| Size | 14.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3869e26c31f78c90715099a57077c100a0d27d2af4db38723ad03960c76caf9a
|
|
BLAKE2b-256 checksum How to use checksums |
db7290f7fcaedce2983134b2ac62fb869f26aac546d57a99292e5304e26ab30f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Linux glibc 2.17+ x86-64 PyPy 3.11 PyPy 3.11 7.3 |
|
SHA-256 checksum How to use checksums |
c1d143149a13339f884fca16e844c671f6b4b1e8a70e04c222f028dd3eeec927
|
|
BLAKE2b-256 checksum How to use checksums |
13b3204480057b1b98cf9d1ab5b152148cc6649bdcf95fecab28889e9d87c7e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp314-cp314-win_amd64.whl
| Download URL | mgcv_rust-0.23.2-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 3.7 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0010d3fdbba5ec3dc6aaa3ba79637eeaeb6d738bff6a80569594bc0f01e17db5
|
|
BLAKE2b-256 checksum How to use checksums |
a34c73d40623fa21cd0869b584bb4835d889fe0f3eb4c8415a517d7dc9251845
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
d3ced513991e01ad8899c4a60832eb652a74fc2229d0b85dba4bc8901dece3e1
|
|
BLAKE2b-256 checksum How to use checksums |
529e47d636b88099adba5610ed8e91d3fc8a8521529b69595ac1bd070f60d19f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | mgcv_rust-0.23.2-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 940.9 kB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
16145cdff9e0364efabd24222dc55b5882556b4e3b8bdcbc0875efd2c246e491
|
|
BLAKE2b-256 checksum How to use checksums |
da0801d75b055354aec059309f24d5f7851aa79d35ece972ba87e6f8655b25c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp313-cp313-win_amd64.whl
| Download URL | mgcv_rust-0.23.2-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 3.7 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0b60422cde585e11b842d2e654fe1252969b07c5479454b8037b64a8da33a25e
|
|
BLAKE2b-256 checksum How to use checksums |
025fa1c4b359d580fa0a63271261cc56d29d2b9be16024d9c60442a37de612fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
00b61bc532dcff62ff2ba4ddcee9a2b60462d813e746e2477a852574a1985c65
|
|
BLAKE2b-256 checksum How to use checksums |
ce23585fb0d503fcff968bc2387d7e2750eb18bc1fb3fba618a6e76c3f6020ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | mgcv_rust-0.23.2-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 939.6 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1d066c746ce389377ff4ce7614ab8ea0295d8126459e60eea16681f4114bdfac
|
|
BLAKE2b-256 checksum How to use checksums |
c1da660a9737f41aa44347fa315af1b4f2cf1dfe3472e93c678b62fe4697d3f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp312-cp312-win_amd64.whl
| Download URL | mgcv_rust-0.23.2-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 3.7 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
1c6542c446b5e7a5ce07c8972008269e3d8c7eb826334978352513d952f3b99c
|
|
BLAKE2b-256 checksum How to use checksums |
28a5d3685549fbe53f2a26e4d6f8598c51ae88157fcf58aa9e12a406446be8b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
7a03f28c96bfe937dc1236b1acb9e069c18cbfdecd24b1c84846c55af75b095b
|
|
BLAKE2b-256 checksum How to use checksums |
f39400a813e23b95c026f59773e38775d477e046df3364abdeed82172d8a1963
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | mgcv_rust-0.23.2-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 940.2 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
87c1a4b55e8affceb16b5441436bb63801e01751e58568df20643fd9d9be6f4c
|
|
BLAKE2b-256 checksum How to use checksums |
ed0d950624338af7a20f65a2aaef186d2dbf67212f59e50d7c79347ce54b03e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp311-cp311-win_amd64.whl
| Download URL | mgcv_rust-0.23.2-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 3.7 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
632231255b3c48153a5ec4e561be2641dfc756b528f57a7aa1c3b1832fa846bd
|
|
BLAKE2b-256 checksum How to use checksums |
a413f6752dc9c533db63ca9ff2cf767ee240a52820759b7472e7bf9761e6d141
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
aa16cf111e775c534faa60882e5099264c955a50bf64c19e8393ef8de3fd1d54
|
|
BLAKE2b-256 checksum How to use checksums |
899daedeb32a399849013451b36661f848662395a8525c2db796ef6ae383a6a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | mgcv_rust-0.23.2-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 942.1 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
14aef7868f488ee8ab539018c3f2fe9a401812a4a8ac2e0b9ba5ea9bf4c84642
|
|
BLAKE2b-256 checksum How to use checksums |
c59252a5c35f177af9a2184833aa8b8c8dc2812eb0311aad2624dc267f4ae95e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp310-cp310-win_amd64.whl
| Download URL | mgcv_rust-0.23.2-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 3.7 MB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a2e867ed34890280ec90d38c08f1ce0972dfd9f02a8c698de1073afb08f62aed
|
|
BLAKE2b-256 checksum How to use checksums |
045f2644499258488408fde22f94e9292484d3ebb6a579c6a3372e290399c7ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
1c69836613f7be093b2529be57c7da6fae6f135b8517154aa1f5129928485103
|
|
BLAKE2b-256 checksum How to use checksums |
034bc3f457614521f77b1b20575a2455680a95b5e660660f5681cf0dfac9e64e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / mgcv_rust-0.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mgcv_rust-0.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
4eb041f982f457b6f84d629e65a8e678af0d0355ffa9d84b79ac12b4c8028b7f
|
|
BLAKE2b-256 checksum How to use checksums |
785650e7cdefcf6d1e347e10d3aeabb5d934fad5012ea74687a5756ab6faadd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Security for mgcv-rust 0.23.2
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.