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.2.tar.gz (48.0 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.2-cp310-abi3-win_amd64.whl (187.9 kB view details)

Uploaded CPython 3.10+Windows x86-64

marshmallow_core-0.1.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (320.2 kB view details)

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

marshmallow_core-0.1.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (320.2 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

marshmallow_core-0.1.2-cp310-abi3-macosx_11_0_arm64.whl (290.0 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: marshmallow_core-0.1.2.tar.gz
  • Upload date:
  • Size: 48.0 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.2.tar.gz
Algorithm Hash digest
SHA256 b8f8e5b5d9cc92d32b84e13889fe5c9bf2a792a9230a500cb162b206a126ac9f
MD5 5855741a112477c1f809481d6e8589d9
BLAKE2b-256 fdde898df0d7f003ac431a9bd4497495b0f602fd49b27dbfbee81ac201c86b91

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.2.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.2-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.2-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 888cd87caec4fa8e3f02a5225df18687a86dc9f0aa45a2845fe14a75bd6d86dd
MD5 71e4b31eae3fe23bdd622ce80e4579bd
BLAKE2b-256 0f3285ee005f63f13330c61e23a149dff9c94e827261bba2fc2e23a793bb9e8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.2-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.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 69f34d45c8adf16eeabf1da0271ebcbe31d4c2e30fbaa523e97607e47a7f39f4
MD5 b40b13895fe30f4a5c40e21791b1f4eb
BLAKE2b-256 bec4b5be6c091013e3054b0f9c19f87dbc968d8f8ffe2da73bdf704ea4fdfc04

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.2-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.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ebf4d286c07c464496ee75cb25d36d4f47e5ba5ee9b765bde4cee338f123d5fd
MD5 7b5b53d84a6e3447d1e4cc9a661dcaaf
BLAKE2b-256 364f9a5d53c6060e09ffdeb2b97bd21e95075d0bb1010486d1f8d0b82ae5946e

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.2-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.2-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for marshmallow_core-0.1.2-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dc4d580f6d9e5c0f640c24d2ae2acc00f3d46a67d377faf5c69aa85dbdfef626
MD5 da0250053dfeb6c7b24f75934f78bd90
BLAKE2b-256 d6eb31a3cf9f2466537472de174e3eeda6e5525bb7242d057e7233dc3cf9da69

See more details on using hashes here.

Provenance

The following attestation bundles were made for marshmallow_core-0.1.2-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