Skip to main content

monty-compat

Release-aware Python source transpilation and capability discovery for the Monty interpreter.

monty-compat learns the exact surface of a released Monty runtime, records that evidence in a versioned manifest, and lowers unsupported Python into semantically equivalent constructs only when the rewrite can be proven safe. When Monty's supported feature set cannot preserve observable Python behavior, the transpiler raises an explicit error instead of inventing semantics.

Documentation · Python API · Release selection · Changelog

Why this exists

Monty intentionally implements a Python subset. File names and Rust symbols can tell us that pathlib.Path exists, but not whether a nested surface such as pathlib.Path.is_dir is available or whether a syntax form parses, type-checks, and behaves like CPython. monty-compat combines three evidence sources:

  1. Static extraction scans Monty's Rust source for builtins, exceptions, modules, module attributes, constructors, and runtime-type attributes.
  2. Behavioral discovery runs atomic probes on both CPython and the exact linked Monty release and classifies the result.
  3. Conservative lowering rewrites only evidence-backed seams for which the required Python semantics can be represented by Monty's supported subset.

Discovery is an offline release-maintenance operation. Default verified transpilation does not download Monty, run probes, start Python workers, or execute the input. The opt-in latest mode performs one bounded, validated manifest-channel resolution per process.

Published packages

Registry Package Purpose
PyPI monty-compat Python API and native PyO3 transpiler
crates.io monty-compat Rust lowering engine and monty-lower CLI
crates.io monty-compat-extract Rust extractor and monty-extract CLI

monty-compat-python and monty-compat-discover are internal workspace crates and are not published separately. All Python, Rust, manifests, documentation, and release automation live in this repository.

Installation

Python runtime:

pip install monty-compat

Python discovery tooling, including exact Monty, pysource-codegen, and pysource-minimize:

pip install 'monty-compat[discovery]'

Rust embedding:

cargo add monty-compat@0.5.0
cargo add monty-compat-extract@0.5.0

The Python wheel uses abi3 and supports CPython 3.10 and newer.

Quick start: transpile and run

The public Python hot path is intentionally one function:

from monty_compat import transpiler
from pydantic_monty import Monty

source = """
value = 2
match value:
    case 2:
        result = f"ok:{value}"
    case _:
        result = "other"
result
"""

lowered = transpiler(source)  # release="verified"

with Monty() as pool:
    with pool.checkout() as session:
        assert session.feed_run(lowered) == "ok:2"

Pin the exact bundled manifest when reproducibility matters:

lowered = transpiler(source, release="0.0.19")
assert lowered == transpiler(source, release="v0.0.19")

verified is the default and resolves to the newest manifest compiled into the installed wheel (0.0.19 in version 0.5.0). It is deterministic and performs no network access. latest is an explicit freshness mode:

lowered = transpiler(source, release="latest")

It downloads the bounded manifest channel from the project documentation, accepts only a SHA-256-matching manifest that declares compatibility with the installed lowering engine, and caches the resulting transpiler for the process. An unavailable, incompatible, or malformed channel fails closed. Exact bundled versions such as 0.0.19 and v0.0.19 remain offline.

The function returns ordinary Python source, so monty-compat does not wrap, own, or replace Monty's execution API.

Failure is explicit

from monty_compat import TranspilationError, transpiler

try:
    transpiler("def values():\n    yield 1\n", release="0.0.19")
except TranspilationError as exc:
    print(exc)

TranspilationError covers:

  • an unbundled release;
  • failure to resolve or validate the opt-in latest channel;
  • invalid Python input;
  • manifest validation failure;
  • needs_review or not_lowerable diagnostics for semantics Monty cannot currently represent.

The Python binding releases the GIL while Rust parses and lowers the source. Successful exact-source results are retained in a process-global, release-pinned, bounded cache. Failures are never cached and cache entries never cross manifests.

Performance

Release-mode measurements below use a 100 KiB source, Rust 1.95.0, and an Apple M1 MacBook Air. p50 and median are the same statistic and are both shown because release reports expose both labels.

Operation Samples p50 Median p99
Supported source, cache disabled 200 4.224 ms 4.224 ms 5.661 ms
Supported source, exact cache hit 20,000 0.0317 ms 0.0317 ms 0.0424 ms
Match-heavy lowering, cache disabled 200 30.957 ms 30.957 ms 32.102 ms
Match-heavy lowering, exact cache hit 20,000 0.0316 ms 0.0316 ms 0.0429 ms
Monty 0.0.19 local source extraction 200 113.419 ms 113.419 ms 132.644 ms
Monty 0.0.19 in-memory ZIP extraction 200 119.257 ms 119.257 ms 136.816 ms

These are local measurements, not latency guarantees. See Benchmark methodology for workloads, commands, raw results, cache-miss interpretation, and reproduction notes.

Capability graph API

Use MontyCapabilities to inspect the exact static surface extracted from Monty's Rust source:

from monty_compat import MontyCapabilities

caps = MontyCapabilities.from_github()  # latest released source
# caps = MontyCapabilities.from_github(only_released=False)  # main branch
# caps = MontyCapabilities.from_local("/path/to/monty")

assert "pathlib" in caps.modules
assert caps.supports_path("pathlib.Path")
assert caps.supports_path("pathlib.Path.is_dir")

path_methods = caps.get_attributes("pathlib.Path")
print(sorted(path_methods))
print(caps.summary())

This graph answers precise questions about known paths; it does not classify a complete Python program or prove that a snippet can run. Use transpiler(...) for the fail-closed source compatibility decision.

The graph contains:

  • builtin_functions
  • type_constructors
  • exception_types
  • modules
  • module_attributes
  • type_attributes, including paths such as str.upper, pathlib.Path.is_dir, and re.Pattern.search

See the Python API reference for every public function, argument, return value, limitation, and error.

Lowering contract

Every non-supported feature in the bundled manifest has one auditable outcome:

Availability Meaning
automatic Every represented occurrence has a semantics-preserving rewrite.
contextual Rewriting is allowed only when conservative static facts prove its preconditions.
not_lowerable Monty's current surface cannot preserve the required behavior.

Current lowering families include:

  • literal, sequence, mapping, OR, guarded, and selected class match cases;
  • function decorators and complex for/with targets;
  • selected class, descriptor, dataclass, and user-class protocol seams;
  • percent formatting, str.format, and custom f-string formatting;
  • dict union, assert messages, Unicode decimal conversion, and static bytes;
  • contextual repairs for selected lazy iterators, class-comprehension scope, closure late binding, async with, and asyncio.gather behavior.

Unsupported semantics remain explicit. The engine does not synthesize exception inheritance, traceback objects, generator suspension, exception groups, runtime type mutation, or dispatch precedence that Monty does not implement.

See Lowering semantics for before/after examples, diagnostics, contextual preconditions, and the non-goals that protect semantic correctness.

Rust API

The core Rust API accepts a caller-supplied exact manifest:

use monty_compat::{CacheConfig, CapabilityIndex, Transpiler};

let manifest = std::fs::read_to_string("manifests/monty-v0.0.19.json")?;
let capabilities = CapabilityIndex::from_json(&manifest)?;
let transpiler = Transpiler::with_cache_config(
    capabilities,
    CacheConfig::default(),
);

let output = transpiler.transpile(
    "value = 1\nmatch value:\n    case 1:\n        result = 'one'\nresult\n",
)?;

assert!(output.changed);
assert_eq!(output.target_tag, "v0.0.19");
println!("{}", output.code);
# Ok::<(), Box<dyn std::error::Error>>(())

Transpiler is thread-safe, owns an immutable manifest index, and returns an Arc<LoweringOutput> so exact cache hits reuse the canonical artifact. Use CacheConfig::disabled() for deterministic cache-free measurements.

The extractor is a separate public crate:

use monty_compat_extract::{extract_release, resolve_release};

let release = resolve_release("0.0.19")?;
let graph = extract_release(&release)?;
assert!(graph.modules.contains("pathlib"));
# Ok::<(), Box<dyn std::error::Error>>(())

See the Rust API and CLI reference for public structs, errors, caching, extraction bounds, and command exit behavior.

Command-line tools

Lower a file and retain a machine-readable diagnostic report:

cargo run -p monty-compat -- \
  --manifest manifests/monty-v0.0.19.json \
  --input example.py \
  --output example.lowered.py \
  --report lowering-report.json \
  --deny-needs-review

monty-lower exits 2 when any seam is needs_review or not_lowerable under --deny-needs-review, and 1 for loading/parsing failures.

Extract a static graph from a checkout or ZIP archive:

cargo run -p monty-compat-extract -- \
  --root /path/to/monty \
  --output monty-static-capabilities.json

cargo run -p monty-compat-extract -- \
  --archive monty-v0.0.19.zip \
  --output monty-static-capabilities.json

ZIP inputs and downloads are size-bounded, validated, and scanned in memory; archives are never unpacked onto the filesystem.

Exact-release discovery

The recommended release pipeline is Rust-orchestrated and links the exact Monty version being measured:

cargo run --release --manifest-path crates/monty-discover/Cargo.toml -- \
  --release 0.0.19 \
  --seeds 1000 \
  --python .venv/bin/python \
  --output manifests/monty-v0.0.19.json

The pipeline:

  1. resolves the requested release and downloads that exact archive;
  2. rejects a source/runtime version mismatch;
  3. extracts the static graph in Rust;
  4. runs baseline semantic probes through killable workers;
  5. generates deterministic inert AST corpora with pysource-codegen;
  6. minimizes failures with pysource-minimize while Rust retains the final same-fingerprint verdict;
  7. atomically writes the versioned manifest.

Generated source is parsed and compiled by CPython, wrapped under if False, and then submitted to Monty. It is never executed directly. Generated failures are discovery evidence and promotion candidates; they never become “supported” without a reviewed semantic probe.

See Discovery and manifest generation for status classes, worker boundaries, manifest schema, minimization, and adding a new Monty release.

Examples

Development and verification

uv sync --locked --extra dev

cargo +1.95.0 fmt --all -- --check
cargo +1.95.0 clippy --workspace --all-targets --locked -- -D warnings
cargo +1.95.0 test --workspace --locked

cargo +1.95.0 test \
  --manifest-path crates/monty-discover/Cargo.toml \
  --locked

uv run pytest -q
uv run ruff check src tests examples
uv run mypy src

uvx --from zensical==0.0.50 zensical build --clean

The differential suite compares original CPython, lowered CPython, and lowered exact-Monty result/exception envelopes plus stdout and stderr:

MONTY_COMPAT_CPYTHON=python3.11 \
cargo test --manifest-path crates/monty-discover/Cargo.toml --test differential

The workspace forbids Rust unsafe. Checked byte ranges, fallible edit planning, malformed-input tests, exact release fingerprints, and RustSec/cargo-deny checks are release gates.

More documentation

License

MIT

Download files

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

Source Distribution

monty_compat-0.5.0.tar.gz (335.2 kB view details)

Uploaded Source

Built Distributions

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

monty_compat-0.5.0-cp310-abi3-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.10+Windows x86-64

monty_compat-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.1 MB view details)

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

monty_compat-0.5.0-cp310-abi3-macosx_11_0_arm64.whl (2.4 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

monty_compat-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file monty_compat-0.5.0.tar.gz.

File metadata

  • Download URL: monty_compat-0.5.0.tar.gz
  • Upload date:
  • Size: 335.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monty_compat-0.5.0.tar.gz
Algorithm Hash digest
SHA256 2d67b898dbca498671fd8f2584b0f7fa691854e220e1b9e8c83cecaf88e22371
MD5 695937811d42f257a784e6b54ae26383
BLAKE2b-256 a51284d5875a569f08c6ece26af096b7a7d4e8597845c0140ed30e776bfd46aa

See more details on using hashes here.

File details

Details for the file monty_compat-0.5.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: monty_compat-0.5.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monty_compat-0.5.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0353f1ac54a16c4f1240a682124367cc680a632ee23e9bc782dc27aa811e7092
MD5 172c0b8be1e75d5d9896d59694cdaf34
BLAKE2b-256 c65b9376761a870125e9588a2e5837457f88a3c28816fb8907ed7b7d39b1a44c

See more details on using hashes here.

File details

Details for the file monty_compat-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: monty_compat-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monty_compat-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b3f4ba00aa11bef1e01f12947938268de68e0c697e3053953982dc0280d04d34
MD5 a8d3cbd07494d8e3daf8d58adb7042a9
BLAKE2b-256 04e9f99faebc59e60ab83311a2da186c08ca130bfcfc92556ca44bc1b71dca43

See more details on using hashes here.

File details

Details for the file monty_compat-0.5.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: monty_compat-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: CPython 3.10+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monty_compat-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1f6f868deb5fbd3491c92838d101f95a8e19df2136d5a4439097a32d4579821f
MD5 dd892db86d0daac25a4af25f66aa99a4
BLAKE2b-256 e78757937c3e91f6c562fe31d3c4e9de039de2d3c836c2196bf85ae5df782275

See more details on using hashes here.

File details

Details for the file monty_compat-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: monty_compat-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: CPython 3.10+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monty_compat-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 eb4f8d36d5304a660ee85820620170f082b36f064ffcec4ab54c3c23e28d8487
MD5 90edf5cc1130b2cd9adb9f8c4e205581
BLAKE2b-256 ce7c40740e2b79c62ecae46ec94c074f7268a53ea422b51547376ad94dbe33e0

See more details on using hashes here.

Supported by

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