Rust/PyO3 accelerator for cerberus: a native, iso-functional Validator with transparent fallback to cerberus.
Project description
pulse-cerberus
A Rust/PyO3 accelerator for cerberus — an iso-functional,
drop-in Validator whose validate() hot path runs in native code, with transparent fallback to
cerberus for anything outside its fast path. It's a separate package that depends on cerberus
and delegates back to it, so it never diverges on input cerberus accepts — by construction.
pip install pulse-cerberus
# was: from cerberus import Validator
from pulse_cerberus import Validator
schema = {
"id": {"type": "integer", "required": True, "min": 1},
"name": {"type": "string", "required": True, "minlength": 1, "maxlength": 64},
"role": {"type": "string", "allowed": ["admin", "user", "guest"]},
"tags": {"type": "list", "schema": {"type": "string"}},
"addr": {"type": "dict", "schema": {"city": {"type": "string"}}},
}
v = Validator(schema) # compiled once
v.validate({"id": 1, "name": "alice", "role": "admin"}) # → True, ~200× faster
v.errors # same .errors tree as cerberus, byte-for-byte
The only change is the import. Validator, .validate(), .validated(), .errors, .document,
SchemaError, DocumentError, registries — the cerberus API works unchanged.
Performance
cerberus's Validator.validate is interpreted Python: per call it re-dispatches every rule, spawns
child-validators for nested schemas, and re-expands the schema. pulse-cerberus compiles the schema
once into a Rust rule-AST and then validates flatly.
Drift-immune A/B (median per call), pre-built validator, realistic schema (8 fields incl. a nested dict and a list), CPython 3.11, Apple Silicon:
median / validate() |
speedup | |
|---|---|---|
cerberus.Validator.validate |
~245 µs | — |
pulse_cerberus.Validator.validate |
~1.2 µs | ~×200 |
The striking part: cerberus pays a large fixed per-call cost (rule dispatch + child-validator spawning
- schema re-expansion) on every
validate(), even for a small document. That interpreted machinery is exactly what a native validator removes. Reproduce it:
import statistics, time, cerberus, pulse_cerberus
schema = {"id": {"type": "integer", "required": True, "min": 1},
"name": {"type": "string", "required": True, "minlength": 1, "maxlength": 64},
"role": {"type": "string", "allowed": ["admin", "user", "guest"]},
"tags": {"type": "list", "schema": {"type": "string"}},
"addr": {"type": "dict", "schema": {"city": {"type": "string"}}}}
doc = {"id": 1, "name": "alice", "role": "admin", "tags": ["x"], "addr": {"city": "Paris"}}
ref = cerberus.Validator(schema) # build once (validators are meant to be reused)
cand = pulse_cerberus.Validator(schema)
def bench(v, reps, rounds=15):
out = []
for _ in range(rounds):
t = time.perf_counter()
for _ in range(reps): v.validate(doc)
out.append((time.perf_counter() - t) / reps)
return statistics.median(out)
r = bench(ref, 2000); c = bench(cand, 20000)
print(f"cerberus {r*1e6:.1f} us -> pulse {c*1e6:.2f} us (x{r/c:.0f})")
Why Rust wins here (and why this is not a false friend)
Profiling validate(): the hot path is interpreted Python (__validate_definitions /
__get_rule_handler per rule×field, child-validator spawning, schema re-expansion), 0 % in the C
re engine. The ~38 % that shows up as "C" is isinstance / abc.__instancecheck__ / dict.get —
dispatch glue that simply evaporates in typed Rust. Because the bottleneck is interpreted Python (not a
C-bound kernel), a native rewrite wins by orders of magnitude.
What's covered natively (and what falls back)
pulse-cerberus validates natively when the schema uses only:
- types
integer/float/number/boolean/string/dict/list(with cerberus's exact bool semantics:integer/floatacceptTrue,numberexcludes it); - rules
required,allowed,min,max,minlength,maxlength,empty,nullable, and nestedschema(dict + list-of), withallow_unknownandrequire_all.
Everything else is transparently delegated to cerberus: normalization (coerce/default/rename/
purge_unknown/readonly), logic (*of, dependencies, excludes), check_with, keysrules/
valuesrules, items, contains, regex, allow_unknown as a rules-set, registries, custom
Validator subclasses, non-dict documents, and exotic value types. A SchemaError is raised at
construction exactly as cerberus would. When in doubt, it falls back — it never guesses.
The error messages are rendered through Python's
str()(cerberus formats its own messages the same way), so the.errorstree — structure, messages, and per-field alphabetical-by-rule order — is identical to cerberus's.
Iso-functionality
Proven by a typed differential oracle comparing (validate(), .errors, .document) against stock
cerberus, on a curated corpus of the iso-critical cases plus adversarial fuzzing of random
(schema, doc) pairs — including the bool subtleties, error ordering, nested/list-of error trees, the
empty/min interaction, and exception parity (SchemaError/DocumentError). The pure-Python
fallback path is verified to be iso too (PULSE_FORCE_FALLBACK=1).
Wheels
abi3 wheels (Python ≥ 3.11) for Linux (x86_64/aarch64, manylinux + musllinux), macOS (Apple Silicon),
and Windows; sdist elsewhere (builds the Rust core via maturin).
License
ISC (same as cerberus).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pulse_cerberus-0.1.0.tar.gz.
File metadata
- Download URL: pulse_cerberus-0.1.0.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8e6be9150ed956c2dbcfd37793864d55b7f08573e271c410b94d246bd9ef866
|
|
| MD5 |
2d9ac160da6203b70b79f56b171c4057
|
|
| BLAKE2b-256 |
d1cdbe187f3a7a813090f67c504c85ba593c4f1f877cdb030e2e578b26881d54
|
Provenance
The following attestation bundles were made for pulse_cerberus-0.1.0.tar.gz:
Publisher:
release.yml on AstekGroup/pulse-cerberus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulse_cerberus-0.1.0.tar.gz -
Subject digest:
a8e6be9150ed956c2dbcfd37793864d55b7f08573e271c410b94d246bd9ef866 - Sigstore transparency entry: 1857749559
- Sigstore integration time:
-
Permalink:
AstekGroup/pulse-cerberus@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AstekGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pulse_cerberus-0.1.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: pulse_cerberus-0.1.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 141.0 kB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7fc44c0e2e009f4433bc500623b3fd3e27b116ae667b05b78aee035eb331f71
|
|
| MD5 |
fc71fef4776b03661c65a816eeb8906a
|
|
| BLAKE2b-256 |
a44cc9cbb87e665bcaccfb275612278fcf9398ccf81ada60f4d9a547838ec8a4
|
Provenance
The following attestation bundles were made for pulse_cerberus-0.1.0-cp311-abi3-win_amd64.whl:
Publisher:
release.yml on AstekGroup/pulse-cerberus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulse_cerberus-0.1.0-cp311-abi3-win_amd64.whl -
Subject digest:
a7fc44c0e2e009f4433bc500623b3fd3e27b116ae667b05b78aee035eb331f71 - Sigstore transparency entry: 1857749725
- Sigstore integration time:
-
Permalink:
AstekGroup/pulse-cerberus@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AstekGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 257.8 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d3e0c10a94096dad1ef79147dffd428c88e8624fae767b79f58821665774f42
|
|
| MD5 |
d56cf942107261505c6e182ad23a2f63
|
|
| BLAKE2b-256 |
4e47e814bb4c79f86492f8c925283b244516d54ff4e3a979a43d9aab783013a6
|
Provenance
The following attestation bundles were made for pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on AstekGroup/pulse-cerberus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
3d3e0c10a94096dad1ef79147dffd428c88e8624fae767b79f58821665774f42 - Sigstore transparency entry: 1857749927
- Sigstore integration time:
-
Permalink:
AstekGroup/pulse-cerberus@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AstekGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 255.9 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6c85c8431ed5109533e24aa8a3478ac2601c1cf6a4b13ee570c527ec0efe8a1
|
|
| MD5 |
0551142c326f70ee4d8ecbcd960c8f99
|
|
| BLAKE2b-256 |
64f25818c22697343d1af79fa00355dbe1a2b9a121c8fe6e2a5907b89c495a30
|
Provenance
The following attestation bundles were made for pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on AstekGroup/pulse-cerberus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulse_cerberus-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
b6c85c8431ed5109533e24aa8a3478ac2601c1cf6a4b13ee570c527ec0efe8a1 - Sigstore transparency entry: 1857750148
- Sigstore integration time:
-
Permalink:
AstekGroup/pulse-cerberus@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AstekGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pulse_cerberus-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: pulse_cerberus-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 234.8 kB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9235f3cb133fc2d2819e113d6beefc854724c35b718bf8d5d4d1d9bb49773ccb
|
|
| MD5 |
c6d43ab3792fc9e666b2a6895be9c31f
|
|
| BLAKE2b-256 |
b77cd18d93c8b7761985cf62f3c3df963f272dcb689be8d95b4fdb86ed5ad78b
|
Provenance
The following attestation bundles were made for pulse_cerberus-0.1.0-cp311-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on AstekGroup/pulse-cerberus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulse_cerberus-0.1.0-cp311-abi3-macosx_11_0_arm64.whl -
Subject digest:
9235f3cb133fc2d2819e113d6beefc854724c35b718bf8d5d4d1d9bb49773ccb - Sigstore transparency entry: 1857749764
- Sigstore integration time:
-
Permalink:
AstekGroup/pulse-cerberus@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AstekGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6e0a8e042a9504c4f84a8c86d8d8dc49204588f -
Trigger Event:
push
-
Statement type: