Skip to main content

Rust acceleration core for marshmallow serialization, installed as a separate, opt-in package.

Project description

marshmallow_core

CI

A Rust acceleration core for marshmallow, shipped as a separate, opt-in package. Install it next to stock marshmallow and activate it explicitly — it replaces marshmallow's per-object _serialize / _deserialize loops with a PyO3 extension while producing identical results.

pip install marshmallow marshmallow_core
import marshmallow as ma
import marshmallow_core

marshmallow_core.install()      # patch marshmallow.Schema in this process

class Person(ma.Schema):
    name = ma.fields.String()
    age = ma.fields.Integer()

Person().load({"name": "ann", "age": "30"})   # accelerated
Person().dump({"name": "ann", "age": 30})      # accelerated

marshmallow_core.uninstall()    # restore the stock pure-Python methods

How it works

  • install() monkey-patches Schema._serialize and Schema._do_load. Each bound schema is compiled once (cached on the instance) into a recursive payload describing every field as either native (run entirely in Rust) or a callback (defers to the Python Field method). Anything not modelled natively stays a callback, so output is behaviour-identical.
  • The load core handles only the happy path: the instant it hits any error/edge case it raises an internal AccelFallback and marshmallow re-runs the unchanged pure-Python load, so every error message and value matches exactly. The dump core has no fallback, so each native dump element is provably identical to Field._serialize.
  • dumps is fused: it writes JSON bytes directly in Rust, skipping the intermediate Python dict and the json.dumps pass, byte-for-byte identical to json.dumps(schema.dump(obj)). It activates for hook-free schemas using the stdlib json render module with no extra json kwargs, and falls back to dump + json.dumps for anything it can't reproduce exactly. (loads is already accelerated through the patched load path; a Rust JSON parser was prototyped but did not beat CPython's C json.loads, so it was not shipped.)
  • Acceleration is strictly a speedup. Set MARSHMALLOW_NO_ACCEL=1 (or hit a protocol-version mismatch between the Python and Rust halves) and the core becomes a no-op even after install().

Scope / limitations

install() accelerates dump for all compilable schemas, and load for most schemas — including those with pre_load / post_load / validates / validates_schema hooks: the core runs the per-field deserialize step while those hooks run in Python around it (mirroring marshmallow's own _do_load split). Recognized field validators (Range / Length / OneOf) run natively; any other validator, or field-level pre_load / post_load, keeps that field on the callback path. unknown=INCLUDE, collection/dotted partial, and dotted attribute writes are all accelerated. Custom dict_class / get_attribute, self-referential schemas, custom strptime temporal formats, and callable defaults always fall back to pure Python.

Development

Requires cargo (rustup) and maturin.

# build + install the extension into the current venv
uvx maturin develop --release

# run the tests (needs marshmallow + pytest installed)
pytest

# force the pure-Python path
MARSHMALLOW_NO_ACCEL=1 pytest

tests/test_equivalence.py asserts that dump/load produce identical output and errors with the core active vs. forced onto pure Python, across scalars, nested/list/enum/temporal/UUID fields, partial=True, and error inputs.

Benchmarking

The performance/ directory (not shipped in wheels) measures the core against stock marshmallow through the public install() / uninstall() API. Run it from the repo root with the compiled extension importable (uvx maturin develop --release first, or point PYTHONPATH at the repo while the wheel is installed):

# stock-vs-core table for dump / load / dumps / loads on four schema shapes
python -m performance.benchmark                       # all cases
python -m performance.benchmark --number 20000 --only flat,list

# coverage probe: per-field native vs callback for each schema shape
python -m performance.analyze_paths

benchmark.py reports per-call microseconds for stock and core plus the speedup ratio, across flat-scalar, nested, list-heavy, and validator-heavy schemas. analyze_paths.py inspects the compiled payload and shows which fields run native in Rust vs. fall back to a Python callback — it tells you exactly where a real schema still defers to pure Python.

Releasing

CI (.github/workflows/ci.yml) builds the wheel and runs the suite against stock marshmallow on Python 3.10–3.13, both with the core active and with MARSHMALLOW_NO_ACCEL=1. Publishing (.github/workflows/release.yml) builds abi3 wheels + sdist for Linux/macOS/Windows on a v* tag and uploads them to PyPI via trusted publishing. Before the first release, configure the PyPI trusted publisher for this repo and create a pypi GitHub Environment, then push a tag (e.g. git tag v0.1.0 && git push --tags).

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

marshmallow_core-0.1.1.tar.gz (46.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

marshmallow_core-0.1.1-cp310-abi3-win_amd64.whl (187.3 kB view details)

Uploaded CPython 3.10+Windows x86-64

marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (319.6 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (319.6 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

marshmallow_core-0.1.1-cp310-abi3-macosx_11_0_arm64.whl (289.4 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file marshmallow_core-0.1.1.tar.gz.

File metadata

  • Download URL: marshmallow_core-0.1.1.tar.gz
  • Upload date:
  • Size: 46.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for marshmallow_core-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4c0228b28b0e9afcc6af8ccc2c292e54fe4a687b8c1bfe9c2d30d20f1ec20d44
MD5 31f2f3552b1b103a964b37994ed86ead
BLAKE2b-256 52c3a3bc1df9d4d5d3012bbeefc7bc508b40399d8d02f415fc7debb5d8363c0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.1.tar.gz:

Publisher: release.yml on gunlinux/marshmallow_core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marshmallow_core-0.1.1-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.1-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7e1f831225c4459c373f3afd8179d2ac0bcef4bd24c9b60bb0073b3d527a47ab
MD5 4e988330748d039f2671ff701439fd78
BLAKE2b-256 d550b3357b0ae9deac0e7748807d836340994d32e4f9dfe59f068c25da8b6d02

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.1-cp310-abi3-win_amd64.whl:

Publisher: release.yml on gunlinux/marshmallow_core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d5cac58c5a7d7b6f6545ac5d9e8c4195179521544d41400697442fce00e04a82
MD5 504823bc5d2d4f65f0eda8bf7823e2a4
BLAKE2b-256 46ae4e2425eb13366a897c8c1f71a51772385968e448865dde81ecd4a842650f

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on gunlinux/marshmallow_core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f1f23490c744172f996817840fe8f583fcacf7eda254fc452996c80a8ec12354
MD5 1dcbc6bf4024e5aee3a932c7f5f2e570
BLAKE2b-256 4f8ccd853fe89fd57e21998e405ba2e504386e26d10b136c04edb1b3c2550e3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on gunlinux/marshmallow_core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marshmallow_core-0.1.1-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.1-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c3f3c36fb17482d20256375fec94e10196b4575961ef23cfedc9d816fff518bc
MD5 c954e8e33c7401ad27d176b6bf5aaa66
BLAKE2b-256 c29c7d443753d1a825d6a912b0e6c191bb5ff5266ea05313dc4f853a31aaeb35

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.1-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on gunlinux/marshmallow_core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page